Merge pull request #252 from eReuse/feature/#3308-device-details
Feature/#3308 device details
This commit is contained in:
commit
3f9e771ad6
|
@ -603,21 +603,39 @@ class AllocateForm(ActionFormMix):
|
||||||
end_users = IntegerField('End users', [validators.Optional()])
|
end_users = IntegerField('End users', [validators.Optional()])
|
||||||
|
|
||||||
def validate(self, extra_validators=None):
|
def validate(self, extra_validators=None):
|
||||||
is_valid = super().validate(extra_validators)
|
if not super().validate(extra_validators):
|
||||||
|
return False
|
||||||
|
|
||||||
if self.type.data not in ['Allocate', 'Deallocate']:
|
if self.type.data not in ['Allocate', 'Deallocate']:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
if not self.validate_dates():
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not self.check_devices():
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def validate_dates(self):
|
||||||
start_time = self.start_time.data
|
start_time = self.start_time.data
|
||||||
end_time = self.end_time.data
|
end_time = self.end_time.data
|
||||||
|
|
||||||
|
if not start_time:
|
||||||
|
self.start_time.errors = ['Not a valid date value.!']
|
||||||
|
return False
|
||||||
|
|
||||||
if start_time and end_time and end_time < start_time:
|
if start_time and end_time and end_time < start_time:
|
||||||
error = ['The action cannot finish before it starts.']
|
error = ['The action cannot finish before it starts.']
|
||||||
self.end_time.errors = error
|
self.end_time.errors = error
|
||||||
is_valid = False
|
return False
|
||||||
|
|
||||||
if is_valid and not end_time:
|
if not end_time:
|
||||||
self.end_time.data = self.start_time.data
|
self.end_time.data = self.start_time.data
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def check_devices(self):
|
||||||
if self.type.data == 'Allocate':
|
if self.type.data == 'Allocate':
|
||||||
txt = "You need deallocate before allocate this device again"
|
txt = "You need deallocate before allocate this device again"
|
||||||
for device in self._devices:
|
for device in self._devices:
|
||||||
|
@ -636,7 +654,7 @@ class AllocateForm(ActionFormMix):
|
||||||
|
|
||||||
device.allocated = False
|
device.allocated = False
|
||||||
|
|
||||||
return is_valid
|
return True
|
||||||
|
|
||||||
|
|
||||||
class DataWipeDocumentForm(Form):
|
class DataWipeDocumentForm(Form):
|
||||||
|
|
|
@ -10,7 +10,7 @@ from typing import Dict, List, Set
|
||||||
from boltons import urlutils
|
from boltons import urlutils
|
||||||
from citext import CIText
|
from citext import CIText
|
||||||
from ereuse_utils.naming import HID_CONVERSION_DOC, Naming
|
from ereuse_utils.naming import HID_CONVERSION_DOC, Naming
|
||||||
from flask import g
|
from flask import g, request
|
||||||
from flask_sqlalchemy import event
|
from flask_sqlalchemy import event
|
||||||
from more_itertools import unique_everseen
|
from more_itertools import unique_everseen
|
||||||
from sqlalchemy import BigInteger, Boolean, Column
|
from sqlalchemy import BigInteger, Boolean, Column
|
||||||
|
@ -297,6 +297,11 @@ class Device(Thing):
|
||||||
actions.reverse()
|
actions.reverse()
|
||||||
return actions
|
return actions
|
||||||
|
|
||||||
|
@property
|
||||||
|
def public_link(self) -> str:
|
||||||
|
host_url = request.host_url.strip('/')
|
||||||
|
return "{}{}".format(host_url, self.url.to_text())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def url(self) -> urlutils.URL:
|
def url(self) -> urlutils.URL:
|
||||||
"""The URL where to GET this device."""
|
"""The URL where to GET this device."""
|
||||||
|
|
|
@ -26,6 +26,14 @@
|
||||||
<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#type">Type</button>
|
<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#type">Type</button>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{ device.public_link }}" target="_blank">Web</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-item">
|
||||||
|
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#lots">Lots</button>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#status">Status</button>
|
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#status">Status</button>
|
||||||
</li>
|
</li>
|
||||||
|
@ -69,6 +77,50 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="tab-pane fade profile-overview" id="lots">
|
||||||
|
<h5 class="card-title">Incoming Lots</h5>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
{% for lot in device.lots %}
|
||||||
|
{% if lot.is_incoming %}
|
||||||
|
<div class="col">
|
||||||
|
<a class="ms-3" href="{{ url_for('inventory.lotdevicelist', lot_id=lot.id) }}">
|
||||||
|
<span>{{ lot.name }}</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h5 class="card-title">Outgoing Lots</h5>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
{% for lot in device.lots %}
|
||||||
|
{% if lot.is_outgoing %}
|
||||||
|
<div class="col">
|
||||||
|
<a class="ms-3" href="{{ url_for('inventory.lotdevicelist', lot_id=lot.id) }}">
|
||||||
|
<span>{{ lot.name }}</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h5 class="card-title">Temporary Lots</h5>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
{% for lot in device.lots %}
|
||||||
|
{% if lot.is_temporary %}
|
||||||
|
<div class="col">
|
||||||
|
<a class="ms-3" href="{{ url_for('inventory.lotdevicelist', lot_id=lot.id) }}">
|
||||||
|
<span>{{ lot.name }}</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="tab-pane fade profile-overview" id="status">
|
<div class="tab-pane fade profile-overview" id="status">
|
||||||
<h5 class="card-title">Status Details</h5>
|
<h5 class="card-title">Status Details</h5>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
@ -668,7 +668,7 @@ def test_action_allocate_error_required(user3: UserClientFlask):
|
||||||
body, status = user3.post(uri, data=data)
|
body, status = user3.post(uri, data=data)
|
||||||
assert status == '200 OK'
|
assert status == '200 OK'
|
||||||
assert 'Action Allocate error' in body
|
assert 'Action Allocate error' in body
|
||||||
assert 'You need to specify a number of users!' in body
|
assert 'Not a valid date value.' in body
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
|
Reference in a new issue