diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 63a0458c..e26265b1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,6 +7,7 @@ repos: rev: 5.9.3 hooks: - id: isort + # args: ["--profile", "black", "--filter-files"] - repo: https://github.com/PyCQA/flake8 rev: 4.0.1 hooks: diff --git a/ereuse_devicehub/cli.py b/ereuse_devicehub/cli.py index 47cece32..67054095 100644 --- a/ereuse_devicehub/cli.py +++ b/ereuse_devicehub/cli.py @@ -1,8 +1,8 @@ import os import click.testing -import ereuse_utils import flask.cli +import ereuse_utils from ereuse_devicehub.config import DevicehubConfig from ereuse_devicehub.devicehub import Devicehub diff --git a/ereuse_devicehub/inventory/forms.py b/ereuse_devicehub/inventory/forms.py index 6b3955de..91b80305 100644 --- a/ereuse_devicehub/inventory/forms.py +++ b/ereuse_devicehub/inventory/forms.py @@ -1,7 +1,6 @@ import copy import json from json.decoder import JSONDecodeError - from boltons.urlutils import URL from flask import g, request from flask_wtf import FlaskForm @@ -139,7 +138,7 @@ class LotDeviceForm(FlaskForm): return bool(self._devices) - def save(self): + def save(self, commit=True): trade = self._lot.trade if trade: for dev in self._devices: @@ -149,12 +148,16 @@ class LotDeviceForm(FlaskForm): if self._devices: self._lot.devices.update(self._devices) db.session.add(self._lot) + + if commit: db.session.commit() - def remove(self): + def remove(self, commit=True): if self._devices: self._lot.devices.difference_update(self._devices) db.session.add(self._lot) + + if commit: db.session.commit() @@ -190,7 +193,7 @@ class LotForm(FlaskForm): return self.id def remove(self): - if self.instance and not self.instance.devices: + if self.instance and not self.instance.trade: self.instance.delete() db.session.commit() return self.instance @@ -541,9 +544,9 @@ class TagDeviceForm(FlaskForm): if self.delete: tags = Tag.query.filter(Tag.owner_id == g.user.id).filter_by( device_id=self.device_id - ) + ).order_by(Tag.id) else: - tags = Tag.query.filter(Tag.owner_id == g.user.id).filter_by(device_id=None) + tags = Tag.query.filter(Tag.owner_id == g.user.id).filter_by(device_id=None).order_by(Tag.id) self.tag.choices = [(tag.id, tag.id) for tag in tags] diff --git a/ereuse_devicehub/inventory/views.py b/ereuse_devicehub/inventory/views.py index f9629e59..0d3f2864 100644 --- a/ereuse_devicehub/inventory/views.py +++ b/ereuse_devicehub/inventory/views.py @@ -1,4 +1,5 @@ import csv +import logging from io import StringIO import flask @@ -6,10 +7,12 @@ import flask_weasyprint from flask import Blueprint, g, make_response, request, url_for from flask.views import View from flask_login import current_user, login_required -from werkzeug.exceptions import NotFound +from requests.exceptions import ConnectionError from sqlalchemy import or_ +from werkzeug.exceptions import NotFound from ereuse_devicehub import messages +from ereuse_devicehub.db import db from ereuse_devicehub.inventory.forms import ( AllocateForm, DataWipeForm, @@ -35,6 +38,8 @@ from ereuse_devicehub.resources.tag.model import Tag # TODO(@slamora): rename base 'inventory.devices' --> 'inventory' devices = Blueprint('inventory.devices', __name__, url_prefix='/inventory') +logger = logging.getLogger(__name__) + class DeviceListMix(View): decorators = [login_required] @@ -43,22 +48,28 @@ class DeviceListMix(View): def get_context(self, lot_id): form_filter = FilterForm() filter_types = form_filter.search() - - lots = Lot.query.outerjoin(Trade) \ - .filter(or_(Trade.user_from == g.user, - Trade.user_to == g.user, - Lot.owner_id == g.user.id)).distinct() + lots = ( + Lot.query.outerjoin(Trade) + .filter( + or_( + Trade.user_from == g.user, + Trade.user_to == g.user, + Lot.owner_id == g.user.id, + ) + ) + .distinct() + ) lot = None tags = ( Tag.query.filter(Tag.owner_id == current_user.id) .filter(Tag.device_id.is_(None)) - .order_by(Tag.created.desc()) + .order_by(Tag.id.asc()) ) if lot_id: lot = lots.filter(Lot.id == lot_id).one() devices = lot.devices - if filter_types: + if "All" not in filter_types: devices = [dev for dev in lot.devices if dev.type in filter_types] devices = sorted(devices, key=lambda x: x.updated, reverse=True) form_new_action = NewActionForm(lot=lot.id) @@ -145,10 +156,11 @@ class LotDeviceAddView(View): def dispatch_request(self): form = LotDeviceForm() if form.validate_on_submit(): - form.save() + form.save(commit=False) messages.success( 'Add devices to lot "{}" successfully!'.format(form._lot.name) ) + db.session.commit() else: messages.error('Error adding devices to lot!') @@ -164,10 +176,11 @@ class LotDeviceDeleteView(View): def dispatch_request(self): form = LotDeviceForm() if form.validate_on_submit(): - form.remove() + form.remove(commit=False) messages.success( 'Remove devices from lot "{}" successfully!'.format(form._lot.name) ) + db.session.commit() else: messages.error('Error removing devices from lot!') @@ -218,6 +231,12 @@ class LotDeleteView(View): def dispatch_request(self, id): form = LotForm(id=id) + if form.instance.trade: + msg = "Sorry, the lot cannot be deleted because have a trade action " + messages.error(msg) + next_url = url_for('inventory.devices.lotdevicelist', lot_id=id) + return flask.redirect(next_url) + form.remove() next_url = url_for('inventory.devices.devicelist') return flask.redirect(next_url) @@ -262,7 +281,7 @@ class TagListView(View): def dispatch_request(self): lots = Lot.query.filter(Lot.owner_id == current_user.id) - tags = Tag.query.filter(Tag.owner_id == current_user.id) + tags = Tag.query.filter(Tag.owner_id == current_user.id).order_by(Tag.id) context = { 'lots': lots, 'tags': tags, @@ -298,7 +317,18 @@ class TagAddUnnamedView(View): context = {'page_title': 'New Unnamed Tag', 'lots': lots} form = TagUnnamedForm() if form.validate_on_submit(): - form.save() + try: + form.save() + except ConnectionError as e: + logger.error( + "Error while trying to connect to tag server: {}".format(e) + ) + msg = ( + "Sorry, we cannot create the unnamed tags requested because " + "some error happens while connecting to the tag server!" + ) + messages.error(msg) + next_url = url_for('inventory.devices.taglist') return flask.redirect(next_url) diff --git a/ereuse_devicehub/resources/device/models.py b/ereuse_devicehub/resources/device/models.py index 16b9df5b..89ddc846 100644 --- a/ereuse_devicehub/resources/device/models.py +++ b/ereuse_devicehub/resources/device/models.py @@ -474,6 +474,13 @@ class Device(Thing): key=attrgetter('type')) # last test of each type return self._warning_actions(current_tests) + @property + def verbose_name(self): + type = self.type or '' + manufacturer = self.manufacturer or '' + model = self.model or '' + return f'{type} {manufacturer} {model}' + @declared_attr def __mapper_args__(cls): """Defines inheritance. diff --git a/ereuse_devicehub/static/js/main_inventory.js b/ereuse_devicehub/static/js/main_inventory.js index d790af81..86c25a82 100644 --- a/ereuse_devicehub/static/js/main_inventory.js +++ b/ereuse_devicehub/static/js/main_inventory.js @@ -59,18 +59,39 @@ function deviceSelect() { } } +function removeLot() { + var devices = $(".deviceSelect"); + if (devices.length > 0) { + $("#btnRemoveLots .text-danger").show(); + } else { + $("#btnRemoveLots .text-danger").hide(); + } + $("#activeRemoveLotModal").click(); +} + function removeTag() { var devices = $(".deviceSelect").filter(':checked'); var devices_id = $.map(devices, function(x) { return $(x).attr('data')}); - if (devices_id.length > 0) { + if (devices_id.length == 1) { var url = "/inventory/tag/devices/"+devices_id[0]+"/del/"; window.location.href = url; + } else { + $("#unlinkTagAlertModal").click(); } } function addTag() { - deviceSelect(); - $("#addingTagModal").click(); + var devices = $(".deviceSelect").filter(':checked'); + var devices_id = $.map(devices, function(x) { return $(x).attr('data')}); + if (devices_id.length == 1) { + $("#addingTagModal .pol").hide(); + $("#addingTagModal .btn-primary").show(); + } else { + $("#addingTagModal .pol").show(); + $("#addingTagModal .btn-primary").hide(); + } + + $("#addTagAlertModal").click(); } function newTrade(action) { diff --git a/ereuse_devicehub/static/js/print.pdf.js b/ereuse_devicehub/static/js/print.pdf.js index d7d9833a..5316e1ef 100644 --- a/ereuse_devicehub/static/js/print.pdf.js +++ b/ereuse_devicehub/static/js/print.pdf.js @@ -65,5 +65,5 @@ function printpdf() { min_tag_side = (Math.min(height, width)/2) + border; pdf.addImage(imgData, 'PNG', border, border, img_side, img_side); pdf.text(tag, max_tag_side, min_tag_side); - pdf.save('Tags.pdf'); + pdf.save('Tag_'+tag+'.pdf'); } diff --git a/ereuse_devicehub/templates/ereuse_devicehub/base.html b/ereuse_devicehub/templates/ereuse_devicehub/base.html index 5ca885f7..7b56a1ec 100644 --- a/ereuse_devicehub/templates/ereuse_devicehub/base.html +++ b/ereuse_devicehub/templates/ereuse_devicehub/base.html @@ -17,9 +17,14 @@ + + + + + diff --git a/ereuse_devicehub/templates/inventory/addDevicestag.html b/ereuse_devicehub/templates/inventory/addDevicestag.html index cb929d37..5170b454 100644 --- a/ereuse_devicehub/templates/inventory/addDevicestag.html +++ b/ereuse_devicehub/templates/inventory/addDevicestag.html @@ -18,7 +18,7 @@

- You need select first some device for adding this in a tag + You need select first one device and only one for add this in a tag

diff --git a/ereuse_devicehub/templates/inventory/alert_unlink_tag_error.html b/ereuse_devicehub/templates/inventory/alert_unlink_tag_error.html new file mode 100644 index 00000000..b05fb40f --- /dev/null +++ b/ereuse_devicehub/templates/inventory/alert_unlink_tag_error.html @@ -0,0 +1,21 @@ + diff --git a/ereuse_devicehub/templates/inventory/device_create.html b/ereuse_devicehub/templates/inventory/device_create.html index 1296531f..8bcb5fae 100644 --- a/ereuse_devicehub/templates/inventory/device_create.html +++ b/ereuse_devicehub/templates/inventory/device_create.html @@ -31,7 +31,7 @@
{{ form.csrf_token }} -
+
@@ -42,8 +42,12 @@
-
- Cancel +
+ {% if form.id %} + Cancel + {% else %} + Cancel + {% endif %}
diff --git a/ereuse_devicehub/templates/inventory/removelot.html b/ereuse_devicehub/templates/inventory/removelot.html index 125d97d3..8e8cfb8f 100644 --- a/ereuse_devicehub/templates/inventory/removelot.html +++ b/ereuse_devicehub/templates/inventory/removelot.html @@ -9,12 +9,15 @@ diff --git a/ereuse_devicehub/templates/inventory/tag_create.html b/ereuse_devicehub/templates/inventory/tag_create.html index 9740ddee..23422ebd 100644 --- a/ereuse_devicehub/templates/inventory/tag_create.html +++ b/ereuse_devicehub/templates/inventory/tag_create.html @@ -33,7 +33,7 @@
{{ form.csrf_token }} -
+
@@ -48,7 +48,7 @@ {% endif %}
-
+
Cancel
diff --git a/ereuse_devicehub/templates/inventory/tag_create_unnamed.html b/ereuse_devicehub/templates/inventory/tag_create_unnamed.html index 96ec073d..a72099d4 100644 --- a/ereuse_devicehub/templates/inventory/tag_create_unnamed.html +++ b/ereuse_devicehub/templates/inventory/tag_create_unnamed.html @@ -33,7 +33,7 @@ {{ form.csrf_token }} -
+
{{ form.amount(class_="form-control") }} @@ -48,7 +48,7 @@ {% endif %}
-
+
Cancel
diff --git a/ereuse_devicehub/templates/inventory/tag_detail.html b/ereuse_devicehub/templates/inventory/tag_detail.html index 331ae80c..3e63ff50 100644 --- a/ereuse_devicehub/templates/inventory/tag_detail.html +++ b/ereuse_devicehub/templates/inventory/tag_detail.html @@ -1,6 +1,5 @@ {% extends "ereuse_devicehub/base_site.html" %} {% block main %} -

Inventory

@@ -35,7 +34,7 @@ @@ -106,7 +105,6 @@
- diff --git a/ereuse_devicehub/templates/inventory/tag_list.html b/ereuse_devicehub/templates/inventory/tag_list.html index 8653605d..b385dfc8 100644 --- a/ereuse_devicehub/templates/inventory/tag_list.html +++ b/ereuse_devicehub/templates/inventory/tag_list.html @@ -1,6 +1,5 @@ {% extends "ereuse_devicehub/base_site.html" %} {% block main %} -

Inventory

@@ -59,7 +58,7 @@ {% if tag.device %} - {{ tag.device.type }} {{ tag.device.manufacturer }} {{ tag.device.model }} + {{ tag.device.verbose_name }} {% endif %} @@ -77,14 +76,8 @@
- - - - {% endblock main %} diff --git a/ereuse_devicehub/templates/inventory/tag_unlink_device.html b/ereuse_devicehub/templates/inventory/tag_unlink_device.html index fb123244..fc6d49d6 100644 --- a/ereuse_devicehub/templates/inventory/tag_unlink_device.html +++ b/ereuse_devicehub/templates/inventory/tag_unlink_device.html @@ -32,7 +32,7 @@ {{ form.csrf_token }} -
+
{{ form.tag(class_="form-control") }} @@ -48,9 +48,9 @@
-
+
Cancel - +
diff --git a/ereuse_devicehub/templates/inventory/trade_document.html b/ereuse_devicehub/templates/inventory/trade_document.html index 01d0d3ed..0fa2fcc6 100644 --- a/ereuse_devicehub/templates/inventory/trade_document.html +++ b/ereuse_devicehub/templates/inventory/trade_document.html @@ -35,22 +35,22 @@ {{ form.csrf_token }} {% for field in form %} {% if field != form.csrf_token %} -
+
{{ field.label(class_="form-label") }} {{ field }} {{ field.description }} - {% endif %} - {% if field.errors %} + {% if field.errors %}

{% for error in field.errors %} {{ error }}
{% endfor %}

- {% endif %} + {% endif %}
+ {% endif %} {% endfor %} -
+
Cancel
diff --git a/ereuse_devicehub/templates/inventory/upload_snapshot.html b/ereuse_devicehub/templates/inventory/upload_snapshot.html index 966cb000..5eb68eb3 100644 --- a/ereuse_devicehub/templates/inventory/upload_snapshot.html +++ b/ereuse_devicehub/templates/inventory/upload_snapshot.html @@ -33,7 +33,7 @@
{{ form.csrf_token }} -
+
{{ form.snapshot }} @@ -54,7 +54,7 @@ {% endif %}
-
+
Cancel
diff --git a/pyproject.toml b/pyproject.toml index 442cc5af..5290743c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,4 +3,4 @@ skip-string-normalization = true target-version = ['py38'] [tool.isort] -multi_line_output = 4 +profile = "black"