Merge pull request #329 from eReuse/feature/3702-update-binding
Feature/3702 update binding
This commit is contained in:
commit
ae653f0987
|
@ -75,7 +75,7 @@ class InventoryView(LoginMixin, SnapshotMixin):
|
||||||
self.response = jsonify(
|
self.response = jsonify(
|
||||||
{
|
{
|
||||||
'url': snapshot.device.url.to_text(),
|
'url': snapshot.device.url.to_text(),
|
||||||
'dhid': snapshot.device.devicehub_id,
|
'dhid': snapshot.device.dhid,
|
||||||
'sid': snapshot.sid,
|
'sid': snapshot.sid,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -110,7 +110,13 @@ class AdvancedSearchForm(FlaskForm):
|
||||||
self.search(dhids)
|
self.search(dhids)
|
||||||
|
|
||||||
def search(self, dhids):
|
def search(self, dhids):
|
||||||
self.devices = Device.query.filter(Device.devicehub_id.in_(dhids))
|
query = Device.query.filter(Device.owner_id == g.user.id)
|
||||||
|
self.devices = query.join(Device.placeholder).filter(
|
||||||
|
or_(
|
||||||
|
Device.devicehub_id.in_(dhids),
|
||||||
|
Placeholder.phid.in_(dhids),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class FilterForm(FlaskForm):
|
class FilterForm(FlaskForm):
|
||||||
|
@ -137,11 +143,11 @@ class FilterForm(FlaskForm):
|
||||||
self.lot = self.lots.filter(Lot.id == self.lot_id).one()
|
self.lot = self.lots.filter(Lot.id == self.lot_id).one()
|
||||||
device_ids = (d.id for d in self.lot.devices)
|
device_ids = (d.id for d in self.lot.devices)
|
||||||
self.devices = Device.query.filter(Device.id.in_(device_ids)).filter(
|
self.devices = Device.query.filter(Device.id.in_(device_ids)).filter(
|
||||||
Device.binding == None
|
Device.binding == None # noqa: E711
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.devices = Device.query.filter(Device.owner_id == g.user.id).filter(
|
self.devices = Device.query.filter(Device.owner_id == g.user.id).filter(
|
||||||
Device.binding == None
|
Device.binding == None # noqa: E711
|
||||||
)
|
)
|
||||||
if self.only_unassigned:
|
if self.only_unassigned:
|
||||||
self.devices = self.devices.filter_by(lots=None)
|
self.devices = self.devices.filter_by(lots=None)
|
||||||
|
@ -364,18 +370,6 @@ class NewDeviceForm(FlaskForm):
|
||||||
if not self.generation.data:
|
if not self.generation.data:
|
||||||
self.generation.data = 1
|
self.generation.data = 1
|
||||||
|
|
||||||
if not self.weight.data:
|
|
||||||
self.weight.data = 0.1
|
|
||||||
|
|
||||||
if not self.height.data:
|
|
||||||
self.height.data = 0.1
|
|
||||||
|
|
||||||
if not self.width.data:
|
|
||||||
self.width.data = 0.1
|
|
||||||
|
|
||||||
if not self.depth.data:
|
|
||||||
self.depth.data = 0.1
|
|
||||||
|
|
||||||
def reset_from_obj(self):
|
def reset_from_obj(self):
|
||||||
if not self._obj:
|
if not self._obj:
|
||||||
return
|
return
|
||||||
|
@ -449,24 +443,28 @@ class NewDeviceForm(FlaskForm):
|
||||||
error = ["Not a correct value"]
|
error = ["Not a correct value"]
|
||||||
is_valid = super().validate(extra_validators)
|
is_valid = super().validate(extra_validators)
|
||||||
|
|
||||||
if self.generation.data < 1:
|
if self.generation.data and self.generation.data < 1:
|
||||||
self.generation.errors = error
|
self.generation.errors = error
|
||||||
is_valid = False
|
is_valid = False
|
||||||
|
|
||||||
if self.weight.data < 0.1:
|
if self.weight.data and not (0.1 <= self.weight.data <= 5):
|
||||||
self.weight.errors = error
|
txt = ["Supported values between 0.1 and 5"]
|
||||||
|
self.weight.errors = txt
|
||||||
is_valid = False
|
is_valid = False
|
||||||
|
|
||||||
if self.height.data < 0.1:
|
if self.height.data and not (0.1 <= self.height.data <= 5):
|
||||||
self.height.errors = error
|
txt = ["Supported values between 0.1 and 5"]
|
||||||
|
self.height.errors = txt
|
||||||
is_valid = False
|
is_valid = False
|
||||||
|
|
||||||
if self.width.data < 0.1:
|
if self.width.data and not (0.1 <= self.width.data <= 5):
|
||||||
self.width.errors = error
|
txt = ["Supported values between 0.1 and 5"]
|
||||||
|
self.width.errors = txt
|
||||||
is_valid = False
|
is_valid = False
|
||||||
|
|
||||||
if self.depth.data < 0.1:
|
if self.depth.data and not (0.1 <= self.depth.data <= 5):
|
||||||
self.depth.errors = error
|
txt = ["Supported values between 0.1 and 5"]
|
||||||
|
self.depth.errors = txt
|
||||||
is_valid = False
|
is_valid = False
|
||||||
|
|
||||||
if self.imei.data and self.amount.data == 1:
|
if self.imei.data and self.amount.data == 1:
|
||||||
|
@ -655,19 +653,30 @@ class NewDeviceForm(FlaskForm):
|
||||||
|
|
||||||
|
|
||||||
class TagDeviceForm(FlaskForm):
|
class TagDeviceForm(FlaskForm):
|
||||||
tag = SelectField('Tag', choices=[])
|
tag = SelectField(
|
||||||
device = StringField('Device', [validators.Optional()])
|
'Tag',
|
||||||
|
choices=[],
|
||||||
|
render_kw={
|
||||||
|
'class': 'form-control selectpicker',
|
||||||
|
'data-live-search': 'true',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.delete = kwargs.pop('delete', None)
|
self.delete = kwargs.pop('delete', None)
|
||||||
self.device_id = kwargs.pop('device', None)
|
self.dhid = kwargs.pop('dhid', None)
|
||||||
|
self._device = (
|
||||||
|
Device.query.filter(Device.devicehub_id == self.dhid)
|
||||||
|
.filter(Device.owner_id == g.user.id)
|
||||||
|
.one()
|
||||||
|
)
|
||||||
|
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
if self.delete:
|
if self.delete:
|
||||||
tags = (
|
tags = (
|
||||||
Tag.query.filter(Tag.owner_id == g.user.id)
|
Tag.query.filter(Tag.owner_id == g.user.id)
|
||||||
.filter_by(device_id=self.device_id)
|
.filter_by(device_id=self._device.id)
|
||||||
.order_by(Tag.id)
|
.order_by(Tag.id)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
@ -695,20 +704,6 @@ class TagDeviceForm(FlaskForm):
|
||||||
self.tag.errors = [("This tag is actualy in use.")]
|
self.tag.errors = [("This tag is actualy in use.")]
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self.device.data:
|
|
||||||
try:
|
|
||||||
self.device.data = int(self.device.data.split(',')[-1])
|
|
||||||
except: # noqa: E722
|
|
||||||
self.device.data = None
|
|
||||||
|
|
||||||
if self.device_id or self.device.data:
|
|
||||||
self.device_id = self.device_id or self.device.data
|
|
||||||
self._device = (
|
|
||||||
Device.query.filter(Device.id == self.device_id)
|
|
||||||
.filter(Device.owner_id == g.user.id)
|
|
||||||
.one()
|
|
||||||
)
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
|
@ -1667,8 +1662,8 @@ class BindingForm(FlaskForm):
|
||||||
self.phid.errors = [txt]
|
self.phid.errors = [txt]
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self.device.is_abstract() != 'Abstract':
|
if self.device.is_abstract() not in ['Abstract', 'Real']:
|
||||||
txt = "This is not a abstract device."
|
txt = "This is not a Abstract or Real device."
|
||||||
self.phid.errors = [txt]
|
self.phid.errors = [txt]
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -1682,7 +1677,7 @@ class BindingForm(FlaskForm):
|
||||||
self.phid.errors = [txt]
|
self.phid.errors = [txt]
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self.placeholder.binding:
|
if self.placeholder.status not in ['Abstract', 'Real']:
|
||||||
txt = "This placeholder have a binding with other device. "
|
txt = "This placeholder have a binding with other device. "
|
||||||
txt += "Before you need to do an unbinding with this other device."
|
txt += "Before you need to do an unbinding with this other device."
|
||||||
self.phid.errors = [txt]
|
self.phid.errors = [txt]
|
||||||
|
|
|
@ -80,7 +80,6 @@ class DeviceListMixin(GenericMixin):
|
||||||
self.context.update(
|
self.context.update(
|
||||||
{
|
{
|
||||||
'devices': devices,
|
'devices': devices,
|
||||||
'form_tag_device': TagDeviceForm(),
|
|
||||||
'form_new_action': form_new_action,
|
'form_new_action': form_new_action,
|
||||||
'form_new_allocate': AllocateForm(lot=lot_id),
|
'form_new_allocate': AllocateForm(lot=lot_id),
|
||||||
'form_new_datawipe': DataWipeForm(lot=lot_id),
|
'form_new_datawipe': DataWipeForm(lot=lot_id),
|
||||||
|
@ -148,27 +147,51 @@ class DeviceDetailView(GenericMixin):
|
||||||
.one()
|
.one()
|
||||||
)
|
)
|
||||||
|
|
||||||
form_binding = BindingForm(device=device)
|
form_tags = TagDeviceForm(dhid=id)
|
||||||
|
|
||||||
self.context.update(
|
self.context.update(
|
||||||
{
|
{
|
||||||
'device': device,
|
'device': device,
|
||||||
'placeholder': device.binding or device.placeholder,
|
'placeholder': device.binding or device.placeholder,
|
||||||
'page_title': 'Device {}'.format(device.devicehub_id),
|
'page_title': 'Device {}'.format(device.devicehub_id),
|
||||||
|
'form_tag_device': form_tags,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return flask.render_template(self.template_name, **self.context)
|
||||||
|
|
||||||
|
|
||||||
|
class BindingSearchView(GenericMixin):
|
||||||
|
methods = ['GET', 'POST']
|
||||||
|
decorators = [login_required]
|
||||||
|
template_name = 'inventory/binding_search.html'
|
||||||
|
|
||||||
|
def dispatch_request(self, dhid):
|
||||||
|
self.get_context()
|
||||||
|
device = (
|
||||||
|
Device.query.filter(Device.owner_id == current_user.id)
|
||||||
|
.filter(Device.devicehub_id == dhid)
|
||||||
|
.one()
|
||||||
|
)
|
||||||
|
|
||||||
|
form_binding = BindingForm(device=device)
|
||||||
|
|
||||||
|
self.context.update(
|
||||||
|
{
|
||||||
|
'page_title': 'Search a Device for to do a binding from {}'.format(
|
||||||
|
device.devicehub_id
|
||||||
|
),
|
||||||
'form_binding': form_binding,
|
'form_binding': form_binding,
|
||||||
'active_binding': False,
|
'device': device,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if form_binding.validate_on_submit():
|
if form_binding.validate_on_submit():
|
||||||
next_url = url_for(
|
next_url = url_for(
|
||||||
'inventory.binding',
|
'inventory.binding',
|
||||||
dhid=form_binding.device.devicehub_id,
|
dhid=dhid,
|
||||||
phid=form_binding.placeholder.phid,
|
phid=form_binding.placeholder.phid,
|
||||||
)
|
)
|
||||||
return flask.redirect(next_url)
|
return flask.redirect(next_url)
|
||||||
elif form_binding.phid.data:
|
|
||||||
self.context['active_binding'] = True
|
|
||||||
|
|
||||||
return flask.render_template(self.template_name, **self.context)
|
return flask.render_template(self.template_name, **self.context)
|
||||||
|
|
||||||
|
@ -179,71 +202,113 @@ class BindingView(GenericMixin):
|
||||||
template_name = 'inventory/binding.html'
|
template_name = 'inventory/binding.html'
|
||||||
|
|
||||||
def dispatch_request(self, dhid, phid):
|
def dispatch_request(self, dhid, phid):
|
||||||
|
self.phid = phid
|
||||||
|
self.dhid = dhid
|
||||||
|
self.next_url = url_for('inventory.device_details', id=dhid)
|
||||||
self.get_context()
|
self.get_context()
|
||||||
device = (
|
self.get_objects()
|
||||||
Device.query.filter(Device.owner_id == g.user.id)
|
if self.check_errors():
|
||||||
.filter(Device.devicehub_id == dhid)
|
return flask.redirect(self.next_url)
|
||||||
.one()
|
|
||||||
)
|
|
||||||
placeholder = (
|
|
||||||
Placeholder.query.filter(Placeholder.owner_id == g.user.id)
|
|
||||||
.filter(Placeholder.phid == phid)
|
|
||||||
.one()
|
|
||||||
)
|
|
||||||
|
|
||||||
if device.is_abstract() != 'Abstract':
|
|
||||||
next_url = url_for('inventory.device_details', id=dhid)
|
|
||||||
messages.error('Device "{}" not is a Abstract device!'.format(dhid))
|
|
||||||
return flask.redirect(next_url)
|
|
||||||
|
|
||||||
if device.placeholder:
|
|
||||||
device = device.placeholder.binding
|
|
||||||
dhid = device.devicehub_id
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
old_placeholder = device.binding
|
return self.post()
|
||||||
old_device_placeholder = old_placeholder.device
|
|
||||||
|
|
||||||
if old_placeholder.is_abstract:
|
|
||||||
for plog in PlaceholdersLog.query.filter_by(
|
|
||||||
placeholder_id=old_placeholder.id
|
|
||||||
):
|
|
||||||
db.session.delete(plog)
|
|
||||||
|
|
||||||
for ac in old_device_placeholder.actions:
|
|
||||||
ac.devices.add(placeholder.device)
|
|
||||||
ac.devices.remove(old_device_placeholder)
|
|
||||||
for act in ac.actions_device:
|
|
||||||
if act.device == old_device_placeholder:
|
|
||||||
db.session.delete(act)
|
|
||||||
|
|
||||||
for tag in list(old_device_placeholder.tags):
|
|
||||||
tag.device = placeholder.device
|
|
||||||
|
|
||||||
db.session.delete(old_device_placeholder)
|
|
||||||
|
|
||||||
device.binding = placeholder
|
|
||||||
db.session.commit()
|
|
||||||
next_url = url_for('inventory.device_details', id=dhid)
|
|
||||||
messages.success(
|
|
||||||
'Device "{}" bind successfully with {}!'.format(dhid, phid)
|
|
||||||
)
|
|
||||||
return flask.redirect(next_url)
|
|
||||||
|
|
||||||
self.context.update(
|
self.context.update(
|
||||||
{
|
{
|
||||||
'device': device.binding.device,
|
'new_placeholder': self.new_placeholder,
|
||||||
'placeholder': placeholder,
|
'old_placeholder': self.old_placeholder,
|
||||||
'page_title': 'Binding confirm',
|
'page_title': 'Binding confirm',
|
||||||
'actions': list(device.binding.device.actions)
|
'actions': list(self.old_device.actions)
|
||||||
+ list(placeholder.device.actions),
|
+ list(self.new_device.actions),
|
||||||
'tags': list(device.binding.device.tags)
|
'tags': list(self.old_device.tags) + list(self.new_device.tags),
|
||||||
+ list(placeholder.device.tags),
|
'dhid': self.dhid,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
return flask.render_template(self.template_name, **self.context)
|
return flask.render_template(self.template_name, **self.context)
|
||||||
|
|
||||||
|
def check_errors(self):
|
||||||
|
if not self.new_placeholder:
|
||||||
|
messages.error('Device Phid: "{}" not exist!'.format(self.phid))
|
||||||
|
return True
|
||||||
|
|
||||||
|
if self.old_device.placeholder.status != 'Abstract':
|
||||||
|
messages.error(
|
||||||
|
'Device Dhid: "{}" is not a Abstract device!'.format(self.dhid)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
|
if self.new_placeholder.status == 'Twin':
|
||||||
|
messages.error('Device Phid: "{}" is a Twin device!'.format(self.phid))
|
||||||
|
return True
|
||||||
|
|
||||||
|
if self.new_placeholder.status == self.old_placeholder.status:
|
||||||
|
txt = 'Device Phid: "{}" and device Dhid: "{}" have the same status, "{}"!'.format(
|
||||||
|
self.phid, self.dhid, self.new_placeholder.status
|
||||||
|
)
|
||||||
|
messages.error(txt)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_objects(self):
|
||||||
|
self.old_device = (
|
||||||
|
Device.query.filter(Device.owner_id == g.user.id)
|
||||||
|
.filter(Device.devicehub_id == self.dhid)
|
||||||
|
.one()
|
||||||
|
)
|
||||||
|
self.new_placeholder = (
|
||||||
|
Placeholder.query.filter(Placeholder.owner_id == g.user.id)
|
||||||
|
.filter(Placeholder.phid == self.phid)
|
||||||
|
.first()
|
||||||
|
)
|
||||||
|
|
||||||
|
if not self.new_placeholder:
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.old_device.placeholder.status == 'Abstract':
|
||||||
|
self.new_device = self.new_placeholder.device
|
||||||
|
self.old_placeholder = self.old_device.placeholder
|
||||||
|
elif self.old_device.placeholder.status == 'Real':
|
||||||
|
self.new_device = self.old_device
|
||||||
|
self.old_placeholder = self.new_placeholder
|
||||||
|
self.old_device = self.old_placeholder.device
|
||||||
|
self.new_placeholder = self.new_device.placeholder
|
||||||
|
|
||||||
|
self.abstract_device = self.old_placeholder.binding
|
||||||
|
self.real_dhid = self.new_device.devicehub_id
|
||||||
|
self.real_phid = self.new_placeholder.phid
|
||||||
|
self.abstract_dhid = self.old_device.devicehub_id
|
||||||
|
self.abstract_phid = self.old_placeholder.phid
|
||||||
|
|
||||||
|
def post(self):
|
||||||
|
for plog in PlaceholdersLog.query.filter_by(
|
||||||
|
placeholder_id=self.old_placeholder.id
|
||||||
|
):
|
||||||
|
db.session.delete(plog)
|
||||||
|
|
||||||
|
for ac in self.old_device.actions:
|
||||||
|
ac.devices.add(self.new_device)
|
||||||
|
ac.devices.remove(self.old_device)
|
||||||
|
for act in ac.actions_device:
|
||||||
|
if act.device == self.old_device:
|
||||||
|
db.session.delete(act)
|
||||||
|
|
||||||
|
for tag in list(self.old_device.tags):
|
||||||
|
tag.device = self.new_device
|
||||||
|
|
||||||
|
db.session.delete(self.old_device)
|
||||||
|
self.abstract_device.binding = self.new_placeholder
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
next_url = url_for('inventory.device_details', id=self.real_dhid)
|
||||||
|
txt = 'Device real with PHID: {} and DHID: {} bind successfully with '
|
||||||
|
txt += 'device abstract PHID: {} DHID: {}.'
|
||||||
|
messages.success(
|
||||||
|
txt.format(
|
||||||
|
self.real_phid, self.real_dhid, self.abstract_phid, self.abstract_dhid
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return flask.redirect(next_url)
|
||||||
|
|
||||||
|
|
||||||
class UnBindingView(GenericMixin):
|
class UnBindingView(GenericMixin):
|
||||||
methods = ['GET', 'POST']
|
methods = ['GET', 'POST']
|
||||||
|
@ -256,31 +321,33 @@ class UnBindingView(GenericMixin):
|
||||||
.filter(Placeholder.phid == phid)
|
.filter(Placeholder.phid == phid)
|
||||||
.one()
|
.one()
|
||||||
)
|
)
|
||||||
if not placeholder.binding:
|
if not placeholder.binding or placeholder.status != 'Twin':
|
||||||
next_url = url_for(
|
next_url = url_for(
|
||||||
'inventory.device_details', id=placeholder.device.devicehub_id
|
'inventory.device_details', id=placeholder.device.devicehub_id
|
||||||
)
|
)
|
||||||
return flask.redirect(next_url)
|
return flask.redirect(next_url)
|
||||||
|
|
||||||
device = placeholder.binding
|
if placeholder.status != 'Twin':
|
||||||
|
dhid = placeholder.device.devicehub_id
|
||||||
if device.is_abstract() != 'Twin':
|
|
||||||
dhid = device.devicehub_id
|
|
||||||
next_url = url_for('inventory.device_details', id=dhid)
|
next_url = url_for('inventory.device_details', id=dhid)
|
||||||
messages.error('Device "{}" not is a Twin device!'.format(dhid))
|
messages.error('Device Dhid: "{}" not is a Twin device!'.format(dhid))
|
||||||
return flask.redirect(next_url)
|
return flask.redirect(next_url)
|
||||||
|
|
||||||
self.get_context()
|
self.get_context()
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
new_device = self.clone_device(device)
|
dhid = placeholder.device.devicehub_id
|
||||||
next_url = url_for('inventory.device_details', id=new_device.devicehub_id)
|
self.clone_device(placeholder.binding)
|
||||||
messages.success('Device "{}" unbind successfully!'.format(phid))
|
next_url = url_for('inventory.device_details', id=dhid)
|
||||||
|
messages.success(
|
||||||
|
'Device with PHID:"{}" and DHID: {} unbind successfully!'.format(
|
||||||
|
phid, dhid
|
||||||
|
)
|
||||||
|
)
|
||||||
return flask.redirect(next_url)
|
return flask.redirect(next_url)
|
||||||
|
|
||||||
self.context.update(
|
self.context.update(
|
||||||
{
|
{
|
||||||
'device': device,
|
|
||||||
'placeholder': placeholder,
|
'placeholder': placeholder,
|
||||||
'page_title': 'Unbinding confirm',
|
'page_title': 'Unbinding confirm',
|
||||||
}
|
}
|
||||||
|
@ -476,12 +543,15 @@ class TagLinkDeviceView(View):
|
||||||
methods = ['POST']
|
methods = ['POST']
|
||||||
decorators = [login_required]
|
decorators = [login_required]
|
||||||
|
|
||||||
def dispatch_request(self):
|
def dispatch_request(self, dhid):
|
||||||
form = TagDeviceForm()
|
form = TagDeviceForm(dhid=dhid)
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
|
tag = form.tag.data
|
||||||
form.save()
|
form.save()
|
||||||
|
|
||||||
return flask.redirect(request.referrer)
|
next_url = url_for('inventory.device_details', id=dhid)
|
||||||
|
messages.success('Tag {} was linked successfully!'.format(tag))
|
||||||
|
return flask.redirect(next_url)
|
||||||
|
|
||||||
|
|
||||||
class TagUnlinkDeviceView(GenericMixin):
|
class TagUnlinkDeviceView(GenericMixin):
|
||||||
|
@ -489,19 +559,20 @@ class TagUnlinkDeviceView(GenericMixin):
|
||||||
decorators = [login_required]
|
decorators = [login_required]
|
||||||
template_name = 'inventory/tag_unlink_device.html'
|
template_name = 'inventory/tag_unlink_device.html'
|
||||||
|
|
||||||
def dispatch_request(self, id):
|
def dispatch_request(self, dhid):
|
||||||
self.get_context()
|
self.get_context()
|
||||||
form = TagDeviceForm(delete=True, device=id)
|
form = TagDeviceForm(delete=True, dhid=dhid)
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
form.remove()
|
form.remove()
|
||||||
|
|
||||||
next_url = url_for('inventory.devicelist')
|
next_url = url_for('inventory.device_details', id=dhid)
|
||||||
|
messages.success('Tag {} was unlinked successfully!'.format(form.tag.data))
|
||||||
return flask.redirect(next_url)
|
return flask.redirect(next_url)
|
||||||
|
|
||||||
self.context.update(
|
self.context.update(
|
||||||
{
|
{
|
||||||
'form': form,
|
'form': form,
|
||||||
'referrer': request.referrer,
|
'dhid': dhid,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1145,10 +1216,11 @@ devices.add_url_rule(
|
||||||
'/device/edit/<string:id>/', view_func=DeviceEditView.as_view('device_edit')
|
'/device/edit/<string:id>/', view_func=DeviceEditView.as_view('device_edit')
|
||||||
)
|
)
|
||||||
devices.add_url_rule(
|
devices.add_url_rule(
|
||||||
'/tag/devices/add/', view_func=TagLinkDeviceView.as_view('tag_devices_add')
|
'/tag/devices/<string:dhid>/add/',
|
||||||
|
view_func=TagLinkDeviceView.as_view('tag_devices_add'),
|
||||||
)
|
)
|
||||||
devices.add_url_rule(
|
devices.add_url_rule(
|
||||||
'/tag/devices/<int:id>/del/',
|
'/tag/devices/<string:dhid>/del/',
|
||||||
view_func=TagUnlinkDeviceView.as_view('tag_devices_del'),
|
view_func=TagUnlinkDeviceView.as_view('tag_devices_del'),
|
||||||
)
|
)
|
||||||
devices.add_url_rule(
|
devices.add_url_rule(
|
||||||
|
@ -1192,3 +1264,7 @@ devices.add_url_rule(
|
||||||
devices.add_url_rule(
|
devices.add_url_rule(
|
||||||
'/unbinding/<string:phid>/', view_func=UnBindingView.as_view('unbinding')
|
'/unbinding/<string:phid>/', view_func=UnBindingView.as_view('unbinding')
|
||||||
)
|
)
|
||||||
|
devices.add_url_rule(
|
||||||
|
'/device/<string:dhid>/binding/',
|
||||||
|
view_func=BindingSearchView.as_view('binding_search'),
|
||||||
|
)
|
||||||
|
|
|
@ -63,6 +63,9 @@ def clone_device(device):
|
||||||
|
|
||||||
if device.type == "Battery":
|
if device.type == "Battery":
|
||||||
device.size
|
device.size
|
||||||
|
|
||||||
|
old_devicehub_id = device.devicehub_id
|
||||||
|
|
||||||
dict_device = copy.copy(device.__dict__)
|
dict_device = copy.copy(device.__dict__)
|
||||||
dict_device.pop('_sa_instance_state')
|
dict_device.pop('_sa_instance_state')
|
||||||
dict_device.pop('id', None)
|
dict_device.pop('id', None)
|
||||||
|
@ -73,6 +76,8 @@ def clone_device(device):
|
||||||
dict_device.pop('tags', None)
|
dict_device.pop('tags', None)
|
||||||
dict_device.pop('system_uuid', None)
|
dict_device.pop('system_uuid', None)
|
||||||
new_device = device.__class__(**dict_device)
|
new_device = device.__class__(**dict_device)
|
||||||
|
new_device.devicehub_id = old_devicehub_id
|
||||||
|
device.devicehub_id = None
|
||||||
db.session.add(new_device)
|
db.session.add(new_device)
|
||||||
|
|
||||||
if hasattr(device, 'components'):
|
if hasattr(device, 'components'):
|
||||||
|
|
|
@ -330,7 +330,7 @@ class Device(Thing):
|
||||||
@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."""
|
||||||
return urlutils.URL(url_for_resource(Device, item_id=self.devicehub_id))
|
return urlutils.URL(url_for_resource(Device, item_id=self.dhid))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rate(self):
|
def rate(self):
|
||||||
|
@ -615,6 +615,14 @@ class Device(Thing):
|
||||||
model = self.model or ''
|
model = self.model or ''
|
||||||
return f'{type} {manufacturer} {model}'
|
return f'{type} {manufacturer} {model}'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dhid(self):
|
||||||
|
if self.placeholder:
|
||||||
|
return self.placeholder.device.devicehub_id
|
||||||
|
if self.binding:
|
||||||
|
return self.binding.device.devicehub_id
|
||||||
|
return self.devicehub_id
|
||||||
|
|
||||||
@declared_attr
|
@declared_attr
|
||||||
def __mapper_args__(cls):
|
def __mapper_args__(cls):
|
||||||
"""Defines inheritance.
|
"""Defines inheritance.
|
||||||
|
@ -924,6 +932,25 @@ class Placeholder(Thing):
|
||||||
)
|
)
|
||||||
owner = db.relationship(User, primaryjoin=owner_id == User.id)
|
owner = db.relationship(User, primaryjoin=owner_id == User.id)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def actions(self):
|
||||||
|
actions = list(self.device.actions) or []
|
||||||
|
|
||||||
|
if self.binding:
|
||||||
|
actions.extend(list(self.binding.actions))
|
||||||
|
|
||||||
|
actions = sorted(actions, key=lambda x: x.created)
|
||||||
|
actions.reverse()
|
||||||
|
return actions
|
||||||
|
|
||||||
|
@property
|
||||||
|
def status(self):
|
||||||
|
if self.is_abstract:
|
||||||
|
return 'Abstract'
|
||||||
|
if self.binding:
|
||||||
|
return 'Twin'
|
||||||
|
return 'Real'
|
||||||
|
|
||||||
|
|
||||||
class Computer(Device):
|
class Computer(Device):
|
||||||
"""A chassis with components inside that can be processed
|
"""A chassis with components inside that can be processed
|
||||||
|
@ -1022,10 +1049,14 @@ class Computer(Device):
|
||||||
"""Returns the privacy of all ``DataStorage`` components when
|
"""Returns the privacy of all ``DataStorage`` components when
|
||||||
it is not None.
|
it is not None.
|
||||||
"""
|
"""
|
||||||
|
components = self.components
|
||||||
|
if self.placeholder and self.placeholder.binding:
|
||||||
|
components = self.placeholder.binding.components
|
||||||
|
|
||||||
return set(
|
return set(
|
||||||
privacy
|
privacy
|
||||||
for privacy in (
|
for privacy in (
|
||||||
hdd.privacy for hdd in self.components if isinstance(hdd, DataStorage)
|
hdd.privacy for hdd in components if isinstance(hdd, DataStorage)
|
||||||
)
|
)
|
||||||
if privacy
|
if privacy
|
||||||
)
|
)
|
||||||
|
|
|
@ -114,7 +114,7 @@ class Device(Thing):
|
||||||
sku = SanitizedStr(description=m.Device.sku.comment)
|
sku = SanitizedStr(description=m.Device.sku.comment)
|
||||||
image = URL(description=m.Device.image.comment)
|
image = URL(description=m.Device.image.comment)
|
||||||
allocated = Boolean(description=m.Device.allocated.comment)
|
allocated = Boolean(description=m.Device.allocated.comment)
|
||||||
devicehub_id = SanitizedStr(
|
dhid = SanitizedStr(
|
||||||
data_key='devicehubID', description=m.Device.devicehub_id.comment
|
data_key='devicehubID', description=m.Device.devicehub_id.comment
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -41,8 +41,8 @@
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="page-header col-md-6 col-md-offset-3">
|
<div class="page-header col-md-6 col-md-offset-3">
|
||||||
<h1>{{ device.__format__('t') }}<br>
|
<h1>{% if abstract %}Real device {% endif %}{{ device.__format__('t') or '' }}<br>
|
||||||
<small>{{ device.__format__('s') }}</small>
|
<small>{{ device.__format__('s') or '' }}</small>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<ul>
|
<ul>
|
||||||
{% for key, value in device.public_properties.items() %}
|
{% for key, value in device.public_properties.items() %}
|
||||||
<li>{{ key }}: {{ value }}</li>
|
<li>{{ key }}: {{ value or '' }}</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
{% if isinstance(device, d.Computer) %}
|
{% if isinstance(device, d.Computer) %}
|
||||||
|
@ -140,17 +140,6 @@
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if device.rate %}
|
|
||||||
<tr class="active">
|
|
||||||
<td class="text-right">
|
|
||||||
Total rate
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{ device.rate.rating_range }}
|
|
||||||
({{ device.rate.rating }})
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
@ -222,6 +211,181 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% if abstract %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="page-header col-md-6 col-md-offset-3">
|
||||||
|
<hr />
|
||||||
|
<h1>Abstract device {{ abstract.__format__('t') or '' }}<br>
|
||||||
|
<small>{{ abstract.__format__('s') or '' }}</small>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-3">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<ul>
|
||||||
|
{% for key, value in abstract.public_properties.items() %}
|
||||||
|
<li>{{ key }}: {{ value or '' }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% if isinstance(abstract, d.Computer) %}
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th>Range</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% if abstract.processor_model %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
CPU – {{ abstract.processor_model }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
Processor Rate = {% if abstract.rate %}
|
||||||
|
{{ abstract.rate.processor_range }}
|
||||||
|
({{ abstract.rate.processor }})
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
{% if abstract.ram_size %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
RAM – {{ abstract.ram_size // 1000 }} GB
|
||||||
|
{{ macros.component_type(abstract.components, 'RamModule') }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
RAM Rate = {% if abstract.rate %}
|
||||||
|
{{ abstract.rate.ram_range }}
|
||||||
|
({{ abstract.rate.ram }})
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
{% if abstract.data_storage_size %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Data Storage – {{ abstract.data_storage_size // 1000 }} GB
|
||||||
|
{{ macros.component_type(abstract.components, 'SolidStateDrive') }}
|
||||||
|
{{ macros.component_type(abstract.components, 'HardDrive') }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
Data Storage Rate = {% if abstract.rate %}
|
||||||
|
{{ abstract.rate.data_storage_range }}
|
||||||
|
({{ abstract.rate.data_storage }})
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
{% if abstract.graphic_card_model %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Graphics – {{ abstract.graphic_card_model }}
|
||||||
|
{{ macros.component_type(abstract.components, 'GraphicCard') }}
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
{% if abstract.network_speeds %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Network –
|
||||||
|
{% if abstract.network_speeds[0] %}
|
||||||
|
Ethernet
|
||||||
|
{% if abstract.network_speeds[0] != None %}
|
||||||
|
max. {{ abstract.network_speeds[0] }} Mbps
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% if abstract.network_speeds[0] and abstract.network_speeds[1] %}
|
||||||
|
+
|
||||||
|
{% endif %}
|
||||||
|
{% if abstract.network_speeds[1] %}
|
||||||
|
WiFi
|
||||||
|
{% if abstract.network_speeds[1] != None %}
|
||||||
|
max. {{ abstract.network_speeds[1] }} Mbps
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{{ macros.component_type(abstract.components, 'NetworkAdapter') }}
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<h4>Actual Status</h4>
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
<strong>
|
||||||
|
Lifecycle Status
|
||||||
|
</strong>
|
||||||
|
—
|
||||||
|
{% if abstract.status %}
|
||||||
|
{{ abstract.status.type }}
|
||||||
|
{% endif %}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>
|
||||||
|
Allocate Status
|
||||||
|
</strong>
|
||||||
|
—
|
||||||
|
{% if abstract.allocated_status %}
|
||||||
|
{{ abstract.allocated_status.type }}
|
||||||
|
{% endif %}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>
|
||||||
|
Physical Status
|
||||||
|
</strong>
|
||||||
|
—
|
||||||
|
{% if abstract.physical_status %}
|
||||||
|
{{ abstract.physical_status.type }}
|
||||||
|
{% endif %}
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h4>Public traceability log of the abstract</h4>
|
||||||
|
<div class="text-right">
|
||||||
|
<small>Latest one.</small>
|
||||||
|
</div>
|
||||||
|
<ol>
|
||||||
|
{% for action in abstract.public_actions %}
|
||||||
|
<li>
|
||||||
|
<strong>
|
||||||
|
{{ abstract.is_status(action) }}
|
||||||
|
{% if not abstract.is_status(action) %}
|
||||||
|
{{ action.type }}
|
||||||
|
{% endif %}
|
||||||
|
</strong>
|
||||||
|
—
|
||||||
|
{% if abstract.is_status(action) %}
|
||||||
|
{{ action }} {{ action.type }}
|
||||||
|
{% else %}
|
||||||
|
{{ action }}
|
||||||
|
{% endif %}
|
||||||
|
<br>
|
||||||
|
<div class="text-muted">
|
||||||
|
<small>
|
||||||
|
{{ action._date_str }}
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
{% if action.certificate %}
|
||||||
|
<a href="{{ action.certificate.to_text() }}">See the certificate</a>
|
||||||
|
{% endif %}
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ol>
|
||||||
|
<div class="text-right">
|
||||||
|
<small>Oldest one.</small>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<footer class="container-fluid footer">
|
<footer class="container-fluid footer">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
@ -2,6 +2,7 @@ import datetime
|
||||||
import uuid
|
import uuid
|
||||||
from itertools import filterfalse
|
from itertools import filterfalse
|
||||||
|
|
||||||
|
import flask
|
||||||
import marshmallow
|
import marshmallow
|
||||||
from flask import Response
|
from flask import Response
|
||||||
from flask import current_app as app
|
from flask import current_app as app
|
||||||
|
@ -110,9 +111,7 @@ class DeviceView(View):
|
||||||
return super().get(id)
|
return super().get(id)
|
||||||
|
|
||||||
def patch(self, id):
|
def patch(self, id):
|
||||||
dev = Device.query.filter_by(
|
dev = Device.query.filter_by(id=id, owner_id=g.user.id, active=True).one()
|
||||||
id=id, owner_id=g.user.id, active=True
|
|
||||||
).one()
|
|
||||||
if isinstance(dev, Computer):
|
if isinstance(dev, Computer):
|
||||||
resource_def = app.resources['Computer']
|
resource_def = app.resources['Computer']
|
||||||
# TODO check how to handle the 'actions_one'
|
# TODO check how to handle the 'actions_one'
|
||||||
|
@ -138,10 +137,17 @@ class DeviceView(View):
|
||||||
return self.one_private(id)
|
return self.one_private(id)
|
||||||
|
|
||||||
def one_public(self, id: int):
|
def one_public(self, id: int):
|
||||||
device = Device.query.filter_by(
|
device = Device.query.filter_by(devicehub_id=id, active=True).one()
|
||||||
devicehub_id=id, active=True
|
abstract = None
|
||||||
).one()
|
if device.binding:
|
||||||
return render_template('devices/layout.html', device=device, states=states)
|
return flask.redirect(device.public_link)
|
||||||
|
|
||||||
|
if device.is_abstract() == 'Twin':
|
||||||
|
abstract = device.placeholder.binding
|
||||||
|
|
||||||
|
return render_template(
|
||||||
|
'devices/layout.html', device=device, states=states, abstract=abstract
|
||||||
|
)
|
||||||
|
|
||||||
@auth.Auth.requires_auth
|
@auth.Auth.requires_auth
|
||||||
def one_private(self, id: str):
|
def one_private(self, id: str):
|
||||||
|
|
|
@ -276,10 +276,10 @@ class DeviceRow(BaseDeviceRow):
|
||||||
software=snapshot.software.name, version=snapshot.version
|
software=snapshot.software.name, version=snapshot.version
|
||||||
)
|
)
|
||||||
# General information about device
|
# General information about device
|
||||||
self['DHID'] = device.devicehub_id
|
self['DHID'] = self.placeholder.device.dhid
|
||||||
self['DocumentID'] = self.document_id
|
self['DocumentID'] = self.document_id
|
||||||
self['Public Link'] = '{url}{id}'.format(
|
self['Public Link'] = '{url}{id}'.format(
|
||||||
url=url_for('Device.main', _external=True), id=device.devicehub_id
|
url=url_for('Device.main', _external=True), id=device.dhid
|
||||||
)
|
)
|
||||||
self['Lots'] = ', '.join([x.name for x in self.device.lots])
|
self['Lots'] = ', '.join([x.name for x in self.device.lots])
|
||||||
for i, tag in zip(range(1, 3), device.tags):
|
for i, tag in zip(range(1, 3), device.tags):
|
||||||
|
|
|
@ -42,13 +42,13 @@
|
||||||
|
|
||||||
<dt>Computer where was erase:</dt>
|
<dt>Computer where was erase:</dt>
|
||||||
<dd>Title: {{ erasure.parent.__format__('ts') }}</dd>
|
<dd>Title: {{ erasure.parent.__format__('ts') }}</dd>
|
||||||
<dd>DevicehubID: {{ erasure.parent.devicehub_id }}</dd>
|
<dd>DevicehubID: {{ erasure.parent.dhid }}</dd>
|
||||||
<dd>Hid: {{ erasure.parent.hid }}</dd>
|
<dd>Hid: {{ erasure.parent.hid }}</dd>
|
||||||
<dd>Tags: {{ erasure.parent.tags }}</dd>
|
<dd>Tags: {{ erasure.parent.tags }}</dd>
|
||||||
|
|
||||||
<dt>Computer where it resides:</dt>
|
<dt>Computer where it resides:</dt>
|
||||||
<dd>Title: {{ erasure.device.parent.__format__('ts') }}</dd>
|
<dd>Title: {{ erasure.device.parent.__format__('ts') }}</dd>
|
||||||
<dd>DevicehubID: {{ erasure.device.parent.devicehub_id }}</dd>
|
<dd>DevicehubID: {{ erasure.device.parent.dhid }}</dd>
|
||||||
<dd>Hid: {{ erasure.device.parent.hid }}</dd>
|
<dd>Hid: {{ erasure.device.parent.hid }}</dd>
|
||||||
<dd>Tags: {{ erasure.device.parent.tags }}</dd>
|
<dd>Tags: {{ erasure.device.parent.tags }}</dd>
|
||||||
|
|
||||||
|
|
|
@ -178,8 +178,6 @@ function deviceSelect() {
|
||||||
$("#addingLotModal .btn-primary").hide();
|
$("#addingLotModal .btn-primary").hide();
|
||||||
$("#removeLotModal .pol").show();
|
$("#removeLotModal .pol").show();
|
||||||
$("#removeLotModal .btn-primary").hide();
|
$("#removeLotModal .btn-primary").hide();
|
||||||
$("#addingTagModal .pol").show();
|
|
||||||
$("#addingTagModal .btn-primary").hide();
|
|
||||||
$("#actionModal .pol").show();
|
$("#actionModal .pol").show();
|
||||||
$("#actionModal .btn-primary").hide();
|
$("#actionModal .btn-primary").hide();
|
||||||
$("#allocateModal .pol").show();
|
$("#allocateModal .pol").show();
|
||||||
|
@ -197,8 +195,6 @@ function deviceSelect() {
|
||||||
$("#allocateModal .btn-primary").show();
|
$("#allocateModal .btn-primary").show();
|
||||||
$("#datawipeModal .pol").hide();
|
$("#datawipeModal .pol").hide();
|
||||||
$("#datawipeModal .btn-primary").show();
|
$("#datawipeModal .btn-primary").show();
|
||||||
$("#addingTagModal .pol").hide();
|
|
||||||
$("#addingTagModal .btn-primary").show();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,33 +210,6 @@ function removeLot() {
|
||||||
$("#activeRemoveLotModal").click();
|
$("#activeRemoveLotModal").click();
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeTag() {
|
|
||||||
const devices = TableController.getSelectedDevices();
|
|
||||||
const devices_id = devices.map(dev => $(dev).attr('data'));
|
|
||||||
|
|
||||||
if (devices_id.length == 1) {
|
|
||||||
const url = "/inventory/tag/devices/".concat(devices_id[0], "/del/");
|
|
||||||
window.location.href = url;
|
|
||||||
} else {
|
|
||||||
$("#unlinkTagAlertModal").click();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addTag() {
|
|
||||||
const devices = TableController.getSelectedDevices();
|
|
||||||
const devices_id = devices.map(dev => $(dev).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 select_shift() {
|
function select_shift() {
|
||||||
const chkboxes = $('.deviceSelect');
|
const chkboxes = $('.deviceSelect');
|
||||||
var lastChecked = null;
|
var lastChecked = null;
|
||||||
|
|
|
@ -163,9 +163,6 @@ function deviceSelect() {
|
||||||
$("#removeLotModal .pol").show();
|
$("#removeLotModal .pol").show();
|
||||||
$("#removeLotModal .btn-primary").hide();
|
$("#removeLotModal .btn-primary").hide();
|
||||||
|
|
||||||
$("#addingTagModal .pol").show();
|
|
||||||
$("#addingTagModal .btn-primary").hide();
|
|
||||||
|
|
||||||
$("#actionModal .pol").show();
|
$("#actionModal .pol").show();
|
||||||
$("#actionModal .btn-primary").hide();
|
$("#actionModal .btn-primary").hide();
|
||||||
|
|
||||||
|
@ -189,9 +186,6 @@ function deviceSelect() {
|
||||||
|
|
||||||
$("#datawipeModal .pol").hide();
|
$("#datawipeModal .pol").hide();
|
||||||
$("#datawipeModal .btn-primary").show();
|
$("#datawipeModal .btn-primary").show();
|
||||||
|
|
||||||
$("#addingTagModal .pol").hide();
|
|
||||||
$("#addingTagModal .btn-primary").show();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,31 +199,6 @@ function removeLot() {
|
||||||
$("#activeRemoveLotModal").click();
|
$("#activeRemoveLotModal").click();
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeTag() {
|
|
||||||
const devices = TableController.getSelectedDevices();
|
|
||||||
const devices_id = devices.map(dev => $(dev).attr("data"));
|
|
||||||
if (devices_id.length == 1) {
|
|
||||||
const url = `/inventory/tag/devices/${devices_id[0]}/del/`;
|
|
||||||
window.location.href = url;
|
|
||||||
} else {
|
|
||||||
$("#unlinkTagAlertModal").click();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addTag() {
|
|
||||||
const devices = TableController.getSelectedDevices();
|
|
||||||
const devices_id = devices.map(dev => $(dev).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 select_shift() {
|
function select_shift() {
|
||||||
const chkboxes = $(".deviceSelect");
|
const chkboxes = $(".deviceSelect");
|
||||||
let lastChecked = null;
|
let lastChecked = null;
|
||||||
|
|
|
@ -256,6 +256,14 @@
|
||||||
</ul>
|
</ul>
|
||||||
</li><!-- End Temporal Lots Nav -->
|
</li><!-- End Temporal Lots Nav -->
|
||||||
|
|
||||||
|
<li class="nav-heading">Unique Identifiers (Tags)</li>
|
||||||
|
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link collapsed" href="{{ url_for('labels.label_list') }}">
|
||||||
|
<i class="bi bi-tag"></i><span>UI Management</span>
|
||||||
|
</a>
|
||||||
|
</li><!-- End Unique Identifiers -->
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</aside><!-- End Sidebar-->
|
</aside><!-- End Sidebar-->
|
||||||
|
|
|
@ -7,16 +7,12 @@
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form action="{{ url_for('inventory.tag_devices_add') }}" method="post">
|
<form action="{{ url_for('inventory.tag_devices_add', dhid=device.devicehub_id) }}" method="post">
|
||||||
{{ form_tag_device.csrf_token }}
|
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
Please write a name of a unique identifier
|
Please write a name of a unique identifier
|
||||||
<select class="form-control selectpicker" id="selectTag" name="tag" data-live-search="true">
|
{% for f in form_tag_device %}
|
||||||
{% for tag in tags %}
|
{{ f }}
|
||||||
<option value="{{ tag.id }}">{{ tag.id }}</option>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
|
||||||
<input class="devicesList" type="hidden" name="device" />
|
|
||||||
<p class="text-danger pol">
|
<p class="text-danger pol">
|
||||||
You need select first one device and only one for add this in a unique identifier
|
You need select first one device and only one for add this in a unique identifier
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -20,115 +20,126 @@
|
||||||
<div class="pt-4 pb-2">
|
<div class="pt-4 pb-2">
|
||||||
<h5 class="card-title text-center pb-0 fs-4">{{ title }}</h5>
|
<h5 class="card-title text-center pb-0 fs-4">{{ title }}</h5>
|
||||||
<p class="text-center">Please check that the information is correct.</p>
|
<p class="text-center">Please check that the information is correct.</p>
|
||||||
|
<p>This is a binding between:
|
||||||
|
<ul>
|
||||||
|
{% if new_placeholder.is_abstract %}
|
||||||
|
<li>1. Device abstract with DHID:<b>{{ new_placeholder.device.devicehub_id }}</b> and PHID: <b>{{ new_placeholder.phid }}</b></li>
|
||||||
|
<li>2. Device real with DHID: <b>{{ old_placeholder.device.devicehub_id }}</b> and PHID:<b>{{ old_placeholder.phid }}</b></li>
|
||||||
|
{% else %}
|
||||||
|
<li>1. Device abstract with DHID:<b>{{ old_placeholder.device.devicehub_id }}</b> and PHID: <b>{{ old_placeholder.phid }}</b></li>
|
||||||
|
<li>2. Device real with DHID: <b>{{ new_placeholder.device.devicehub_id }}</b> and PHID:<b>{{ new_placeholder.phid }}</b></li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
<p>The DHID and PHID information of the abstract will be lost.</p>
|
||||||
|
<p>The information in <span class="text-danger">red colour</span> will be losted and replaced by the information in <span class="text-success">green colour</span>.<br />
|
||||||
|
The information in <span class="text-warning">orange</span> will be replaced by the information in <span class="text-success">green</span> and you always can recover
|
||||||
|
it by doing an unbinding action or find this information into device details web.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="text-center">
|
<tr class="text-center">
|
||||||
<th scope="col">Basic Data</th>
|
<th scope="col">Basic Data</th>
|
||||||
<th scope="col">Info to be Entered</th>
|
<th scope="col">Info Twin device</th>
|
||||||
<th scope="col">Info to be Decoupled</th>
|
<th scope="col">Info Abstract device</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
|
||||||
<th scope="row">PHID:</th>
|
|
||||||
<td class="table-success text-right">{{ placeholder.phid or '' }}</td>
|
|
||||||
<td class="table-danger">{{ device.placeholder.phid or '' }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Manufacturer:</th>
|
<th scope="row">Manufacturer:</th>
|
||||||
<td class="table-success text-right">{{ placeholder.device.manufacturer or '' }}</td>
|
<td class="table-success text-right">{{ new_placeholder.device.manufacturer or '' }}</td>
|
||||||
<td class="table-danger">{{ device.manufacturer or '' }}</td>
|
<td class="table-warning">{{ old_placeholder.device.manufacturer or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Model:</th>
|
<th scope="row">Model:</th>
|
||||||
<td class="table-success">{{ placeholder.device.model or '' }}</td>
|
<td class="table-success">{{ new_placeholder.device.model or '' }}</td>
|
||||||
<td class="table-danger">{{ device.model or '' }}</td>
|
<td class="table-warning">{{ old_placeholder.device.model or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Serial Number:</th>
|
<th scope="row">Serial Number:</th>
|
||||||
<td class="table-success">{{ placeholder.device.serial_number or '' }}</td>
|
<td class="table-success">{{ new_placeholder.device.serial_number or '' }}</td>
|
||||||
<td class="table-danger">{{ device.serial_number or '' }}</td>
|
<td class="table-warning">{{ old_placeholder.device.serial_number or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Brand:</th>
|
<th scope="row">Brand:</th>
|
||||||
<td class="table-success">{{ placeholder.device.brand or '' }}</td>
|
<td class="table-success">{{ new_placeholder.device.brand or '' }}</td>
|
||||||
<td class="table-danger">{{ device.brand or '' }}</td>
|
<td class="table-warning">{{ old_placeholder.device.brand or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Sku:</th>
|
<th scope="row">Sku:</th>
|
||||||
<td class="table-success">{{ placeholder.device.sku or '' }}</td>
|
<td class="table-success">{{ new_placeholder.device.sku or '' }}</td>
|
||||||
<td class="table-danger">{{ device.sku or '' }}</td>
|
<td class="table-warning">{{ old_placeholder.device.sku or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Generation:</th>
|
<th scope="row">Generation:</th>
|
||||||
<td class="table-success">{{ placeholder.device.generation or '' }}</td>
|
<td class="table-success">{{ new_placeholder.device.generation or '' }}</td>
|
||||||
<td class="table-danger">{{ device.generation or '' }}</td>
|
<td class="table-warning">{{ old_placeholder.device.generation or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Version:</th>
|
<th scope="row">Version:</th>
|
||||||
<td class="table-success">{{ placeholder.device.version or '' }}</td>
|
<td class="table-success">{{ new_placeholder.device.version or '' }}</td>
|
||||||
<td class="table-danger">{{ device.version or '' }}</td>
|
<td class="table-warning">{{ old_placeholder.device.version or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Weight:</th>
|
<th scope="row">Weight:</th>
|
||||||
<td class="table-success">{{ placeholder.device.weight or '' }}</td>
|
<td class="table-success">{{ new_placeholder.device.weight or '' }}</td>
|
||||||
<td class="table-danger">{{ device.weight or '' }}</td>
|
<td class="table-warning">{{ old_placeholder.device.weight or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Width:</th>
|
<th scope="row">Width:</th>
|
||||||
<td class="table-success">{{ placeholder.device.width or '' }}</td>
|
<td class="table-success">{{ new_placeholder.device.width or '' }}</td>
|
||||||
<td class="table-danger">{{ device.width or '' }}</td>
|
<td class="table-warning">{{ old_placeholder.device.width or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Height:</th>
|
<th scope="row">Height:</th>
|
||||||
<td class="table-success">{{ placeholder.device.height or '' }}</td>
|
<td class="table-success">{{ new_placeholder.device.height or '' }}</td>
|
||||||
<td class="table-danger">{{ device.height or '' }}</td>
|
<td class="table-warning">{{ old_placeholder.device.height or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Depth:</th>
|
<th scope="row">Depth:</th>
|
||||||
<td class="table-success">{{ placeholder.device.depth or '' }}</td>
|
<td class="table-success">{{ new_placeholder.device.depth or '' }}</td>
|
||||||
<td class="table-danger">{{ device.depth or '' }}</td>
|
<td class="table-warning">{{ old_placeholder.device.depth or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Color:</th>
|
<th scope="row">Color:</th>
|
||||||
<td class="table-success">{{ placeholder.device.color or '' }}</td>
|
<td class="table-success">{{ new_placeholder.device.color or '' }}</td>
|
||||||
<td class="table-danger">{{ device.color or '' }}</td>
|
<td class="table-warning">{{ old_placeholder.device.color or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Production date:</th>
|
<th scope="row">Production date:</th>
|
||||||
<td class="table-success">{{ placeholder.device.production_date or '' }}</td>
|
<td class="table-success">{{ new_placeholder.device.production_date or '' }}</td>
|
||||||
<td class="table-danger">{{ device.production_date or '' }}</td>
|
<td class="table-warning">{{ old_placeholder.device.production_date or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Variant:</th>
|
<th scope="row">Variant:</th>
|
||||||
<td class="table-success">{{ placeholder.device.variant or '' }}</td>
|
<td class="table-success">{{ new_placeholder.device.variant or '' }}</td>
|
||||||
<td class="table-danger">{{ device.variant or '' }}</td>
|
<td class="table-warning">{{ old_placeholder.device.variant or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
{% if placeholder.device.components or device.components %}
|
{% if new_placeholder.device.components or old_placeholder.device.components %}
|
||||||
<h2>Components</h2>
|
<h2>Components</h2>
|
||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="text-center">
|
<tr class="text-center">
|
||||||
<th scope="col">Info to be Entered</th>
|
<th scope="col">Info Twin device</th>
|
||||||
<th scope="col">Info to be Decoupled</th>
|
<th scope="col">Info Abstract device</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="table-success text-right">
|
<td class="table-success text-right">
|
||||||
{% for c in placeholder.device.components %}
|
{% for c in new_placeholder.device.components %}
|
||||||
* {{ c.verbose_name }}<br />
|
* {{ c.verbose_name }}<br />
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</td>
|
</td>
|
||||||
<td class="table-danger">
|
<td class="table-warning">
|
||||||
{% for c in device.components %}
|
{% for c in old_placeholder.device.components %}
|
||||||
* {{ c.verbose_name }}<br />
|
* {{ c.verbose_name }}<br />
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</td>
|
</td>
|
||||||
|
@ -141,11 +152,14 @@
|
||||||
|
|
||||||
{% if actions %}
|
{% if actions %}
|
||||||
<h2>Actions</h2>
|
<h2>Actions</h2>
|
||||||
|
<p>
|
||||||
|
The actions will become real device and will no longer be in the abstract
|
||||||
|
</p>
|
||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="text-center">
|
<tr class="text-center">
|
||||||
<th scope="col">Info to be Entered</th>
|
<th scope="col">Info Twin device</th>
|
||||||
<th scope="col">Info to be Decoupled</th>
|
<th scope="col">Info Abstract device</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -166,11 +180,14 @@
|
||||||
|
|
||||||
{% if tags %}
|
{% if tags %}
|
||||||
<h2>Tags</h2>
|
<h2>Tags</h2>
|
||||||
|
<p>
|
||||||
|
The tags will become real device and will no longer be in the abstract
|
||||||
|
</p>
|
||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="text-center">
|
<tr class="text-center">
|
||||||
<th scope="col">Info to be Entered</th>
|
<th scope="col">Info Twin device</th>
|
||||||
<th scope="col">Info to be Decoupled</th>
|
<th scope="col">Info Abstract device</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -189,7 +206,7 @@
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<form method="post">
|
<form method="post">
|
||||||
<a href="{{ url_for('inventory.device_details', id=device.placeholder.binding.devicehub_id) }}" class="btn btn-danger">Cancel</a>
|
<a href="{{ url_for('inventory.device_details', id=dhid) }}" class="btn btn-danger">Cancel</a>
|
||||||
<button class="btn btn-primary" type="submit">Confirm</button>
|
<button class="btn btn-primary" type="submit">Confirm</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
{% extends "ereuse_devicehub/base_site.html" %}
|
||||||
|
{% block main %}
|
||||||
|
|
||||||
|
<div class="pagetitle">
|
||||||
|
<h1>Inventory</h1>
|
||||||
|
<nav>
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li class="breadcrumb-item"><a href="{{ url_for('inventory.devicelist')}}">Inventory</a></li>
|
||||||
|
<li class="breadcrumb-item active">{{ page_title }}</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
</div><!-- End Page Title -->
|
||||||
|
|
||||||
|
<section class="section profile">
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<div class="col-xl-12">
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body pt-3">
|
||||||
|
<h3>{{ device.devicehub_id }}</h3>
|
||||||
|
<!-- Bordered Tabs -->
|
||||||
|
<div class="tab-content pt-2">
|
||||||
|
|
||||||
|
<div class="tab-pane fade show active">
|
||||||
|
<h5 class="card-title">Binding</h5>
|
||||||
|
{% if device.is_abstract() == 'Twin' or not device.placeholder %}
|
||||||
|
<div class="list-group col-6">
|
||||||
|
<p>
|
||||||
|
Device with Dhid: {{ device.devicehub_id }} is a Twin device.<br />
|
||||||
|
If you want to do a binding with this device, you need todo an Unbinding first.<br />
|
||||||
|
You can to do this in <a href="{{ url_for('inventory.unbinding', phid=device.placeholder.phid) }}" class="help">here</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="list-group col-6">
|
||||||
|
<p>
|
||||||
|
Be careful, binding implies changes in the data of a device that affect its traceability.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="list-group col-6">
|
||||||
|
<form action="{{ url_for('inventory.binding_search', dhid=device.devicehub_id) }}" method="post">
|
||||||
|
{{ form_binding.csrf_token }}
|
||||||
|
{% for field in form_binding %}
|
||||||
|
{% if field != form_binding.csrf_token %}
|
||||||
|
|
||||||
|
<div class="col-12">
|
||||||
|
{{ field.label(class_="form-label") }}:
|
||||||
|
{{ field }}
|
||||||
|
{% if field.errors %}
|
||||||
|
<p class="text-danger">
|
||||||
|
{% for error in field.errors %}
|
||||||
|
{{ error }}<br/>
|
||||||
|
{% endfor %}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
<div class="col-12 mt-2">
|
||||||
|
<input type="submit" class="btn btn-primary" value="Search" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% endblock main %}
|
|
@ -18,25 +18,48 @@
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body pt-3">
|
<div class="card-body pt-3">
|
||||||
<h3>{{ device.devicehub_id }}</h3>
|
<h3>{{ placeholder.device.devicehub_id }}</h3>
|
||||||
|
<div class="tab-pane active show mb-5">
|
||||||
|
<div class="btn-group dropdown" uib-dropdown="" style="float: right; margin-right: 15px;">
|
||||||
|
<button id="btnUniqueID" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
<i class="bi bi-tag"></i>
|
||||||
|
Unique Identifiers (Tags)
|
||||||
|
</button>
|
||||||
|
<span class="d-none" id="unlinkTagAlertModal" data-bs-toggle="modal" data-bs-target="#unlinkTagErrorModal"></span>
|
||||||
|
<span class="d-none" id="addTagAlertModal" data-bs-toggle="modal" data-bs-target="#addingTagModal"></span>
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="btnUniqueID">
|
||||||
|
<li>
|
||||||
|
<a href="javascript:addTag()" class="dropdown-item">
|
||||||
|
<i class="bi bi-plus"></i>
|
||||||
|
Add Unique Identifier
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ url_for('inventory.tag_devices_del', dhid=placeholder.device.devicehub_id) }}" class="dropdown-item">
|
||||||
|
<i class="bi bi-x"></i>
|
||||||
|
Remove Unique Identifier
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% if placeholder.status in ['Abstract', 'Real'] %}
|
||||||
|
<a type="button" href="{{ url_for('inventory.binding_search', dhid=placeholder.device.devicehub_id) }}" class="btn btn-primary" style="float: right; margin-right: 15px;">
|
||||||
|
Binding
|
||||||
|
</a>
|
||||||
|
{% elif placeholder.status == 'Twin' %}
|
||||||
|
<a type="button" href="{{ url_for('inventory.unbinding', phid=placeholder.phid) }}" class="btn btn-primary" style="float: right; margin-right: 15px;">
|
||||||
|
Unbinding
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
<div style="display: block;"></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
<!-- Bordered Tabs -->
|
<!-- Bordered Tabs -->
|
||||||
<ul class="nav nav-tabs nav-tabs-bordered">
|
<ul class="nav nav-tabs nav-tabs-bordered">
|
||||||
|
|
||||||
{% if placeholder %}
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{{ url_for('inventory.device_details', id=placeholder.device.devicehub_id) }}">Placeholder device</a>
|
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#details">General details</button>
|
||||||
</li>
|
</li>
|
||||||
{% else %}
|
|
||||||
<li class="nav-item">
|
|
||||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#type">General details</button>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if placeholder.binding %}
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="{{ url_for('inventory.device_details', id=placeholder.binding.devicehub_id) }}">Workbench device</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{{ device.public_link }}" target="_blank">Web</a>
|
<a class="nav-link" href="{{ device.public_link }}" target="_blank">Web</a>
|
||||||
|
@ -50,10 +73,6 @@
|
||||||
<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>
|
||||||
|
|
||||||
<li class="nav-item">
|
|
||||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#rate">Rate</button>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#traceability">Traceability log</button>
|
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#traceability">Traceability log</button>
|
||||||
</li>
|
</li>
|
||||||
|
@ -62,65 +81,72 @@
|
||||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#components">Components</button>
|
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#components">Components</button>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
{% if device.is_abstract() == 'Abstract' %}
|
|
||||||
<li class="nav-item">
|
|
||||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#binding">Binding</button>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if device.is_abstract() == 'Twin' %}
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="{{ url_for('inventory.unbinding', phid=placeholder.phid) }}">Unbinding</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<div class="tab-content pt-2">
|
<div class="tab-content pt-2">
|
||||||
|
|
||||||
<div class="tab-pane fade {% if active_binding %}profile-overview{% else %}show active{% endif %}" id="type">
|
<div class="tab-pane fade show active" id="details">
|
||||||
<h5 class="card-title">Details</h5>
|
<h5 class="card-title">Details Real parth</h5>
|
||||||
{% if device.placeholder %}
|
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<div class="col-lg-3 col-md-4 label ">
|
<div class="col-lg-3 col-md-4 label ">
|
||||||
(<a href="{{ url_for('inventory.device_edit', id=device.devicehub_id)}}">Edit Device</a>)
|
(<a href="{{ url_for('inventory.device_edit', id=placeholder.device.devicehub_id)}}">Edit Device</a>)
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-9 col-md-8">{{ device.is_abstract() }}</div>
|
<div class="col-lg-9 col-md-8">{{ placeholder.status }}</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if device.placeholder %}
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3 col-md-4 label ">Phid</div>
|
<div class="col-lg-3 col-md-4 label ">Phid</div>
|
||||||
<div class="col-lg-9 col-md-8">{{ device.placeholder.phid }}</div>
|
<div class="col-lg-9 col-md-8">{{ placeholder.phid }}</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3 col-md-4 label ">Type</div>
|
<div class="col-lg-3 col-md-4 label ">Type</div>
|
||||||
<div class="col-lg-9 col-md-8">{{ device.type }}</div>
|
<div class="col-lg-9 col-md-8">{{ placeholder.device.type }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3 col-md-4 label">Manufacturer</div>
|
<div class="col-lg-3 col-md-4 label">Manufacturer</div>
|
||||||
<div class="col-lg-9 col-md-8">{{ device.manufacturer or ''}}</div>
|
<div class="col-lg-9 col-md-8">{{ placeholder.device.manufacturer or ''}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3 col-md-4 label">Model</div>
|
<div class="col-lg-3 col-md-4 label">Model</div>
|
||||||
<div class="col-lg-9 col-md-8">{{ device.model or ''}}</div>
|
<div class="col-lg-9 col-md-8">{{ placeholder.device.model or ''}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3 col-md-4 label">Serial Number</div>
|
<div class="col-lg-3 col-md-4 label">Serial Number</div>
|
||||||
<div class="col-lg-9 col-md-8">{{ device.serial_number or ''}}</div>
|
<div class="col-lg-9 col-md-8">{{ placeholder.device.serial_number or ''}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if placeholder.binding %}
|
||||||
|
<h5 class="card-title">Details Abstract parth</h5>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-3 col-md-4 label ">Type</div>
|
||||||
|
<div class="col-lg-9 col-md-8">{{ placeholder.binding.type }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-3 col-md-4 label">Manufacturer</div>
|
||||||
|
<div class="col-lg-9 col-md-8">{{ placeholder.binding.manufacturer or ''}}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-3 col-md-4 label">Model</div>
|
||||||
|
<div class="col-lg-9 col-md-8">{{ placeholder.binding.model or ''}}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-3 col-md-4 label">Serial Number</div>
|
||||||
|
<div class="col-lg-9 col-md-8">{{ placeholder.binding.serial_number or ''}}</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab-pane fade profile-overview" id="lots">
|
<div class="tab-pane fade profile-overview" id="lots">
|
||||||
<h5 class="card-title">Incoming Lots</h5>
|
<h5 class="card-title">Incoming Lots</h5>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for lot in device.lots %}
|
{% for lot in placeholder.device.lots %}
|
||||||
{% if lot.is_incoming %}
|
{% if lot.is_incoming %}
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<a class="ms-3" href="{{ url_for('inventory.lotdevicelist', lot_id=lot.id) }}">
|
<a class="ms-3" href="{{ url_for('inventory.lotdevicelist', lot_id=lot.id) }}">
|
||||||
|
@ -134,7 +160,7 @@
|
||||||
<h5 class="card-title">Outgoing Lots</h5>
|
<h5 class="card-title">Outgoing Lots</h5>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for lot in device.lots %}
|
{% for lot in placeholder.device.lots %}
|
||||||
{% if lot.is_outgoing %}
|
{% if lot.is_outgoing %}
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<a class="ms-3" href="{{ url_for('inventory.lotdevicelist', lot_id=lot.id) }}">
|
<a class="ms-3" href="{{ url_for('inventory.lotdevicelist', lot_id=lot.id) }}">
|
||||||
|
@ -148,7 +174,7 @@
|
||||||
<h5 class="card-title">Temporary Lots</h5>
|
<h5 class="card-title">Temporary Lots</h5>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for lot in device.lots %}
|
{% for lot in placeholder.device.lots %}
|
||||||
{% if lot.is_temporary %}
|
{% if lot.is_temporary %}
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<a class="ms-3" href="{{ url_for('inventory.lotdevicelist', lot_id=lot.id) }}">
|
<a class="ms-3" href="{{ url_for('inventory.lotdevicelist', lot_id=lot.id) }}">
|
||||||
|
@ -165,53 +191,33 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3 col-md-4 label">Physical State</div>
|
<div class="col-lg-3 col-md-4 label">Physical State</div>
|
||||||
<div class="col-lg-9 col-md-8">
|
<div class="col-lg-9 col-md-8">
|
||||||
{% if device.physical_status %}
|
{% if placeholder.device.physical_status %}
|
||||||
{{ device.physical_status.type }}
|
{{ placeholder.device.physical_status.type }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3 col-md-4 label">Lifecycle State</div>
|
<div class="col-lg-3 col-md-4 label">Lifecycle State</div>
|
||||||
<div class="col-lg-9 col-md-8">
|
<div class="col-lg-9 col-md-8">
|
||||||
{% if device.status %}
|
{% if placeholder.device.status %}
|
||||||
{{ device.status.type }}
|
{{ placeholder.device.status.type }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3 col-md-4 label">Allocated State</div>
|
<div class="col-lg-3 col-md-4 label">Allocated State</div>
|
||||||
<div class="col-lg-9 col-md-8">
|
<div class="col-lg-9 col-md-8">
|
||||||
{% if device.allocated_status %}
|
{% if placeholder.device.allocated_status %}
|
||||||
{{ device.allocated_status.type }}
|
{{ placeholder.device.allocated_status.type }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab-pane fade profile-overview" id="rate">
|
|
||||||
<h5 class="card-title">Rate Details</h5>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-3 col-md-4 label">Rating</div>
|
|
||||||
<div class="col-lg-9 col-md-8">{{ device.rate or '' }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-3 col-md-4 label">Processor</div>
|
|
||||||
<div class="col-lg-9 col-md-8">{{ device.rate.processor or '' }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-3 col-md-4 label">RAM</div>
|
|
||||||
<div class="col-lg-9 col-md-8">{{ device.rate.ram or '' }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-3 col-md-4 label">Data storage</div>
|
|
||||||
<div class="col-lg-9 col-md-8">{{ device.rate.data_storage or '' }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="tab-pane fade profile-overview" id="traceability">
|
<div class="tab-pane fade profile-overview" id="traceability">
|
||||||
<h5 class="card-title">Traceability log Details</h5>
|
<h5 class="card-title">Traceability log Details</h5>
|
||||||
<div class="list-group col-6">
|
<div class="list-group col-6">
|
||||||
{% for action in device.reverse_actions %}
|
{% for action in placeholder.actions %}
|
||||||
<div class="list-group-item d-flex justify-content-between align-items-center">
|
<div class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
{{ action.type }} {{ action.severity }}
|
{{ action.type }} {{ action.severity }}
|
||||||
<small class="text-muted">{{ action.created.strftime('%H:%M %d-%m-%Y') }}</small>
|
<small class="text-muted">{{ action.created.strftime('%H:%M %d-%m-%Y') }}</small>
|
||||||
|
@ -221,10 +227,15 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab-pane fade profile-overview" id="components">
|
<div class="tab-pane fade profile-overview" id="components">
|
||||||
<h5 class="card-title">Components Details</h5>
|
<h5 class="card-title">Components Real parth</h5>
|
||||||
{% if device.binding %}
|
|
||||||
<div class="list-group col-6">
|
<div class="list-group col-6">
|
||||||
{% for component in device.components|sort(attribute='type') %}
|
{{ placeholder.components or '' }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if placeholder.binding %}
|
||||||
|
<h5 class="card-title">Components Abstract parth</h5>
|
||||||
|
<div class="list-group col-6">
|
||||||
|
{% for component in placeholder.binding.components|sort(attribute='type') %}
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<div class="d-flex w-100 justify-content-between">
|
<div class="d-flex w-100 justify-content-between">
|
||||||
<h5 class="mb-1">{{ component.type }}</h5>
|
<h5 class="mb-1">{{ component.type }}</h5>
|
||||||
|
@ -242,52 +253,27 @@
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
|
||||||
<div class="col-6">
|
|
||||||
{{ device.placeholder.components or '' }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if device.is_abstract() %}
|
|
||||||
<div class="tab-pane fade {% if active_binding %}show active{% else %}profile-overview{% endif %}" id="binding">
|
|
||||||
<h5 class="card-title">Binding</h5>
|
|
||||||
<div class="list-group col-6">
|
|
||||||
<p>
|
|
||||||
Be careful, binding implies changes in the data of a device that affect its
|
|
||||||
traceability.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="list-group col-6">
|
|
||||||
<form action="{{ url_for('inventory.device_details', id=device.devicehub_id) }}" method="post">
|
|
||||||
{{ form_binding.csrf_token }}
|
|
||||||
{% for field in form_binding %}
|
|
||||||
{% if field != form_binding.csrf_token %}
|
|
||||||
|
|
||||||
<div class="col-12">
|
|
||||||
{{ field.label(class_="form-label") }}:
|
|
||||||
{{ field }}
|
|
||||||
{% if field.errors %}
|
|
||||||
<p class="text-danger">
|
|
||||||
{% for error in field.errors %}
|
|
||||||
{{ error }}<br/>
|
|
||||||
{% endfor %}
|
|
||||||
</p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
<div class="col-12 mt-2">
|
|
||||||
<input type="submit" class="btn btn-primary" value="Search" />
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function addTag() {
|
||||||
|
const devices_id = [{{ placeholder.device.id }}];
|
||||||
|
if (devices_id.length == 1) {
|
||||||
|
$("#addingTagModal .pol").hide();
|
||||||
|
$("#addingTagModal .btn-primary").show();
|
||||||
|
} else {
|
||||||
|
$("#addingTagModal .pol").show();
|
||||||
|
$("#addingTagModal .btn-primary").hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#addTagAlertModal").click();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{% include "inventory/addDevicestag.html" %}
|
||||||
{% endblock main %}
|
{% endblock main %}
|
||||||
|
|
|
@ -268,42 +268,11 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="btn-group dropdown m-1" uib-dropdown="">
|
|
||||||
<button id="btnUniqueID" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
|
||||||
<i class="bi bi-tag"></i>
|
|
||||||
Unique Identifiers (Tags)
|
|
||||||
</button>
|
|
||||||
<span class="d-none" id="unlinkTagAlertModal" data-bs-toggle="modal" data-bs-target="#unlinkTagErrorModal"></span>
|
|
||||||
<span class="d-none" id="addTagAlertModal" data-bs-toggle="modal" data-bs-target="#addingTagModal"></span>
|
|
||||||
<ul class="dropdown-menu" aria-labelledby="btnUniqueID">
|
|
||||||
<li>
|
|
||||||
<a href="javascript:addTag()" class="dropdown-item">
|
|
||||||
<i class="bi bi-plus"></i>
|
|
||||||
Add Unique Identifier to selected Device
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="javascript:removeTag()" class="dropdown-item">
|
|
||||||
<i class="bi bi-x"></i>
|
|
||||||
Remove Unique Identifier from selected Device
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a class="dropdown-item" href="{{ url_for('labels.label_list')}}">
|
|
||||||
<i class="bi bi-tools"></i>
|
|
||||||
Unique Identifier Management
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="btn-group dropdown m-1" uib-dropdown="">
|
<div class="btn-group dropdown m-1" uib-dropdown="">
|
||||||
<button id="btnTags" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
<button id="btnTags" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
<i class="bi bi-tag"></i>
|
<i class="bi bi-tag"></i>
|
||||||
Labels
|
Labels
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none" id="unlinkTagAlertModal" data-bs-toggle="modal" data-bs-target="#unlinkTagErrorModal"></span>
|
|
||||||
<span class="d-none" id="addTagAlertModal" data-bs-toggle="modal" data-bs-target="#addingTagModal"></span>
|
|
||||||
<ul class="dropdown-menu" aria-labelledby="btnTags">
|
<ul class="dropdown-menu" aria-labelledby="btnTags">
|
||||||
<li>
|
<li>
|
||||||
<form id="print_labels" method="post" action="{{ url_for('labels.print_labels') }}">
|
<form id="print_labels" method="post" action="{{ url_for('labels.print_labels') }}">
|
||||||
|
@ -322,19 +291,9 @@
|
||||||
<div class="btn-group dropdown m-1" uib-dropdown="">
|
<div class="btn-group dropdown m-1" uib-dropdown="">
|
||||||
<button id="btnSnapshot" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
<button id="btnSnapshot" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
<i class="bi bi-laptop"></i>
|
<i class="bi bi-laptop"></i>
|
||||||
New Devices
|
New Devices Real
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu" aria-labelledby="btnSnapshot">
|
<ul class="dropdown-menu" aria-labelledby="btnSnapshot">
|
||||||
<li>
|
|
||||||
{% if lot %}
|
|
||||||
<a href="{{ url_for('inventory.lot_upload_snapshot', lot_id=lot.id) }}" class="dropdown-item">
|
|
||||||
{% else %}
|
|
||||||
<a href="{{ url_for('inventory.upload_snapshot') }}" class="dropdown-item">
|
|
||||||
{% endif %}
|
|
||||||
<i class="bi bi-upload"></i>
|
|
||||||
Upload Snapshot files
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
{% if lot %}
|
{% if lot %}
|
||||||
<a href="{{ url_for('inventory.lot_upload_placeholder', lot_id=lot.id) }}" class="dropdown-item">
|
<a href="{{ url_for('inventory.lot_upload_placeholder', lot_id=lot.id) }}" class="dropdown-item">
|
||||||
|
@ -358,6 +317,25 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-group dropdown m-1" uib-dropdown="">
|
||||||
|
<button id="btnSnapshot" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
<i class="bi bi-laptop"></i>
|
||||||
|
New Devices Abstract
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="btnSnapshot">
|
||||||
|
<li>
|
||||||
|
{% if lot %}
|
||||||
|
<a href="{{ url_for('inventory.lot_upload_snapshot', lot_id=lot.id) }}" class="dropdown-item">
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ url_for('inventory.upload_snapshot') }}" class="dropdown-item">
|
||||||
|
{% endif %}
|
||||||
|
<i class="bi bi-upload"></i>
|
||||||
|
Upload Snapshot files
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% if lot and not lot.is_temporary %}
|
{% if lot and not lot.is_temporary %}
|
||||||
<div class="btn-group dropdown ml-1" uib-dropdown="">
|
<div class="btn-group dropdown ml-1" uib-dropdown="">
|
||||||
<button id="btnSnapshot" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
<button id="btnSnapshot" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
@ -610,14 +588,12 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{% include "inventory/addDevicestag.html" %}
|
|
||||||
{% include "inventory/lot_delete_modal.html" %}
|
{% include "inventory/lot_delete_modal.html" %}
|
||||||
{% include "inventory/actions.html" %}
|
{% include "inventory/actions.html" %}
|
||||||
{% include "inventory/allocate.html" %}
|
{% include "inventory/allocate.html" %}
|
||||||
{% include "inventory/data_wipe.html" %}
|
{% include "inventory/data_wipe.html" %}
|
||||||
{% include "inventory/trade.html" %}
|
{% include "inventory/trade.html" %}
|
||||||
{% include "inventory/alert_export_error.html" %}
|
{% include "inventory/alert_export_error.html" %}
|
||||||
{% include "inventory/alert_unlink_tag_error.html" %}
|
|
||||||
{% include "inventory/alert_lots_changes.html" %}
|
{% include "inventory/alert_lots_changes.html" %}
|
||||||
|
|
||||||
<!-- Custom Code -->
|
<!-- Custom Code -->
|
||||||
|
|
|
@ -40,18 +40,6 @@
|
||||||
<dt>Data storage:</dt>
|
<dt>Data storage:</dt>
|
||||||
<dd>{{ erasure.device.__format__('ts') }}</dd>
|
<dd>{{ erasure.device.__format__('ts') }}</dd>
|
||||||
|
|
||||||
<dt>Computer where was erase:</dt>
|
|
||||||
<dd>Title: {{ erasure.parent.__format__('ts') }}</dd>
|
|
||||||
<dd>DevicehubID: {{ erasure.parent.devicehub_id }}</dd>
|
|
||||||
<dd>Hid: {{ erasure.parent.hid }}</dd>
|
|
||||||
<dd>Tags: {{ erasure.parent.tags }}</dd>
|
|
||||||
|
|
||||||
<dt>Computer where it resides:</dt>
|
|
||||||
<dd>Title: {{ erasure.device.parent.__format__('ts') }}</dd>
|
|
||||||
<dd>DevicehubID: {{ erasure.device.parent.devicehub_id }}</dd>
|
|
||||||
<dd>Hid: {{ erasure.device.parent.hid }}</dd>
|
|
||||||
<dd>Tags: {{ erasure.device.parent.tags }}</dd>
|
|
||||||
|
|
||||||
<dt>Erasure:</dt>
|
<dt>Erasure:</dt>
|
||||||
<dd>{{ erasure.__format__('ts') }}</dd>
|
<dd>{{ erasure.__format__('ts') }}</dd>
|
||||||
{% if erasure.steps %}
|
{% if erasure.steps %}
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if devices %}
|
{% if devices.count() %}
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body pt-3" style="min-height: 650px;">
|
<div class="card-body pt-3" style="min-height: 650px;">
|
||||||
<!-- Bordered Tabs -->
|
<!-- Bordered Tabs -->
|
||||||
|
@ -178,42 +178,11 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="btn-group dropdown m-1" uib-dropdown="">
|
|
||||||
<button id="btnUniqueID" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
|
||||||
<i class="bi bi-tag"></i>
|
|
||||||
Unique Identifiers (Tags)
|
|
||||||
</button>
|
|
||||||
<span class="d-none" id="unlinkTagAlertModal" data-bs-toggle="modal" data-bs-target="#unlinkTagErrorModal"></span>
|
|
||||||
<span class="d-none" id="addTagAlertModal" data-bs-toggle="modal" data-bs-target="#addingTagModal"></span>
|
|
||||||
<ul class="dropdown-menu" aria-labelledby="btnUniqueID">
|
|
||||||
<li>
|
|
||||||
<a href="javascript:addTag()" class="dropdown-item">
|
|
||||||
<i class="bi bi-plus"></i>
|
|
||||||
Add Unique Identifier to selected Device
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="javascript:removeTag()" class="dropdown-item">
|
|
||||||
<i class="bi bi-x"></i>
|
|
||||||
Remove Unique Identifier from selected Device
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a class="dropdown-item" href="{{ url_for('labels.label_list')}}">
|
|
||||||
<i class="bi bi-tools"></i>
|
|
||||||
Unique Identifier Management
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="btn-group dropdown m-1" uib-dropdown="">
|
<div class="btn-group dropdown m-1" uib-dropdown="">
|
||||||
<button id="btnTags" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
<button id="btnTags" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
<i class="bi bi-tag"></i>
|
<i class="bi bi-tag"></i>
|
||||||
Labels
|
Labels
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none" id="unlinkTagAlertModal" data-bs-toggle="modal" data-bs-target="#unlinkTagErrorModal"></span>
|
|
||||||
<span class="d-none" id="addTagAlertModal" data-bs-toggle="modal" data-bs-target="#addingTagModal"></span>
|
|
||||||
<ul class="dropdown-menu" aria-labelledby="btnTags">
|
<ul class="dropdown-menu" aria-labelledby="btnTags">
|
||||||
<li>
|
<li>
|
||||||
<form id="print_labels" method="post" action="{{ url_for('labels.print_labels') }}">
|
<form id="print_labels" method="post" action="{{ url_for('labels.print_labels') }}">
|
||||||
|
@ -232,17 +201,17 @@
|
||||||
<div class="btn-group dropdown m-1" uib-dropdown="">
|
<div class="btn-group dropdown m-1" uib-dropdown="">
|
||||||
<button id="btnSnapshot" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
<button id="btnSnapshot" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
<i class="bi bi-laptop"></i>
|
<i class="bi bi-laptop"></i>
|
||||||
New Device
|
New Device Real
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu" aria-labelledby="btnSnapshot">
|
<ul class="dropdown-menu" aria-labelledby="btnSnapshot">
|
||||||
<li>
|
<li>
|
||||||
{% if lot %}
|
{% if lot %}
|
||||||
<a href="{{ url_for('inventory.lot_upload_snapshot', lot_id=lot.id) }}" class="dropdown-item">
|
<a href="{{ url_for('inventory.lot_upload_placeholder', lot_id=lot.id) }}" class="dropdown-item">
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ url_for('inventory.upload_snapshot') }}" class="dropdown-item">
|
<a href="{{ url_for('inventory.upload_placeholder') }}" class="dropdown-item">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<i class="bi bi-upload"></i>
|
<i class="bi bi-upload"></i>
|
||||||
Upload a new Snapshot
|
Upload Placeholder Spreadsheet
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
@ -252,7 +221,26 @@
|
||||||
<a href="{{ url_for('inventory.device_add') }}" class="dropdown-item">
|
<a href="{{ url_for('inventory.device_add') }}" class="dropdown-item">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<i class="bi bi-plus"></i>
|
<i class="bi bi-plus"></i>
|
||||||
Create a new Device
|
Create a new Placeholder
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-group dropdown m-1" uib-dropdown="">
|
||||||
|
<button id="btnSnapshot" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
<i class="bi bi-laptop"></i>
|
||||||
|
New Device Abstract
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="btnSnapshot">
|
||||||
|
<li>
|
||||||
|
{% if lot %}
|
||||||
|
<a href="{{ url_for('inventory.lot_upload_snapshot', lot_id=lot.id) }}" class="dropdown-item">
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ url_for('inventory.upload_snapshot') }}" class="dropdown-item">
|
||||||
|
{% endif %}
|
||||||
|
<i class="bi bi-upload"></i>
|
||||||
|
Upload Snapshot files
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -287,6 +275,8 @@
|
||||||
<th scope="col">Select</th>
|
<th scope="col">Select</th>
|
||||||
<th scope="col">Title</th>
|
<th scope="col">Title</th>
|
||||||
<th scope="col">DHID</th>
|
<th scope="col">DHID</th>
|
||||||
|
<th scope="col">PHID</th>
|
||||||
|
<th scope="col">Type</th>
|
||||||
<th scope="col">Unique Identifiers</th>
|
<th scope="col">Unique Identifiers</th>
|
||||||
<th scope="col">Lifecycle Status</th>
|
<th scope="col">Lifecycle Status</th>
|
||||||
<th scope="col">Allocated Status</th>
|
<th scope="col">Allocated Status</th>
|
||||||
|
@ -328,6 +318,12 @@
|
||||||
{{ dev.devicehub_id }}
|
{{ dev.devicehub_id }}
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ dev.binding and dev.binding.phid or dev.placeholder and dev.placeholder.phid or '' }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ dev.is_abstract() }}
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{% for t in dev.tags | sort(attribute="id") %}
|
{% for t in dev.tags | sort(attribute="id") %}
|
||||||
<a href="{{ url_for('labels.label_details', id=t.id)}}">{{ t.id }}</a>
|
<a href="{{ url_for('labels.label_details', id=t.id)}}">{{ t.id }}</a>
|
||||||
|
@ -392,14 +388,12 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{% include "inventory/addDevicestag.html" %}
|
|
||||||
{% include "inventory/lot_delete_modal.html" %}
|
{% include "inventory/lot_delete_modal.html" %}
|
||||||
{% include "inventory/actions.html" %}
|
{% include "inventory/actions.html" %}
|
||||||
{% include "inventory/allocate.html" %}
|
{% include "inventory/allocate.html" %}
|
||||||
{% include "inventory/data_wipe.html" %}
|
{% include "inventory/data_wipe.html" %}
|
||||||
{% include "inventory/trade.html" %}
|
{% include "inventory/trade.html" %}
|
||||||
{% include "inventory/alert_export_error.html" %}
|
{% include "inventory/alert_export_error.html" %}
|
||||||
{% include "inventory/alert_unlink_tag_error.html" %}
|
|
||||||
{% include "inventory/alert_lots_changes.html" %}
|
{% include "inventory/alert_lots_changes.html" %}
|
||||||
|
|
||||||
<!-- Custom Code -->
|
<!-- Custom Code -->
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
<input class="devicesList" type="hidden" name="device" />
|
<input class="devicesList" type="hidden" name="device" />
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<a href="{{ referrer }}" class="btn btn-danger">Cancel</a>
|
<a href="{{ url_for('inventory.device_details', id=dhid) }}" class="btn btn-danger">Cancel</a>
|
||||||
<button class="btn btn-primary" type="submit">Unlink</button>
|
<button class="btn btn-primary" type="submit">Unlink</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -26,111 +26,101 @@
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="text-center">
|
<tr class="text-center">
|
||||||
<th scope="col">Basic Data</th>
|
<th scope="col">Basic Data</th>
|
||||||
<th scope="col">Info to be Entered</th>
|
<th scope="col">Info Abstract device</th>
|
||||||
<th scope="col">Info to be Decoupled</th>
|
<th scope="col">Info Real device</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
|
||||||
<th scope="row">PHID:</th>
|
|
||||||
<td class="table-success"></td>
|
|
||||||
<td class="table-danger text-right">{{ placeholder.phid or '' }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Manufacturer:</th>
|
<th scope="row">Manufacturer:</th>
|
||||||
<td class="table-success">{{ device.manufacturer or '' }}</td>
|
<td class="table-success">{{ placeholder.binding.manufacturer or '' }}</td>
|
||||||
<td class="table-danger text-right">{{ placeholder.device.manufacturer or '' }}</td>
|
<td class="table-warning text-right">{{ placeholder.device.manufacturer or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Model:</th>
|
<th scope="row">Model:</th>
|
||||||
<td class="table-success">{{ device.model or '' }}</td>
|
<td class="table-success">{{ placeholder.binding.model or '' }}</td>
|
||||||
<td class="table-danger">{{ placeholder.device.model or '' }}</td>
|
<td class="table-warning">{{ placeholder.device.model or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Serial Number:</th>
|
<th scope="row">Serial Number:</th>
|
||||||
<td class="table-success">{{ device.serial_number or '' }}</td>
|
<td class="table-success">{{ placeholder.binding.serial_number or '' }}</td>
|
||||||
<td class="table-danger">{{ placeholder.device.serial_number or '' }}</td>
|
<td class="table-warning">{{ placeholder.device.serial_number or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Brand:</th>
|
<th scope="row">Brand:</th>
|
||||||
<td class="table-success">{{ device.brand or '' }}</td>
|
<td class="table-success">{{ placeholder.binding.brand or '' }}</td>
|
||||||
<td class="table-danger">{{ placeholder.device.brand or '' }}</td>
|
<td class="table-warning">{{ placeholder.device.brand or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Sku:</th>
|
<th scope="row">Sku:</th>
|
||||||
<td class="table-success">{{ device.sku or '' }}</td>
|
<td class="table-success">{{ placeholder.binding.sku or '' }}</td>
|
||||||
<td class="table-danger">{{ placeholder.device.sku or '' }}</td>
|
<td class="table-warning">{{ placeholder.device.sku or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Generation:</th>
|
<th scope="row">Generation:</th>
|
||||||
<td class="table-success">{{ device.generation or '' }}</td>
|
<td class="table-success">{{ placeholder.binding.generation or '' }}</td>
|
||||||
<td class="table-danger">{{ placeholder.device.generation or '' }}</td>
|
<td class="table-warning">{{ placeholder.device.generation or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Version:</th>
|
<th scope="row">Version:</th>
|
||||||
<td class="table-success">{{ device.version or '' }}</td>
|
<td class="table-success">{{ placeholder.binding.version or '' }}</td>
|
||||||
<td class="table-danger">{{ placeholder.device.version or '' }}</td>
|
<td class="table-warning">{{ placeholder.device.version or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Weight:</th>
|
<th scope="row">Weight:</th>
|
||||||
<td class="table-success">{{ device.weight or '' }}</td>
|
<td class="table-success">{{ placeholder.binding.weight or '' }}</td>
|
||||||
<td class="table-danger">{{ placeholder.device.weight or '' }}</td>
|
<td class="table-warning">{{ placeholder.device.weight or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Width:</th>
|
<th scope="row">Width:</th>
|
||||||
<td class="table-success">{{ device.width or '' }}</td>
|
<td class="table-success">{{ placeholder.binding.width or '' }}</td>
|
||||||
<td class="table-danger">{{ placeholder.device.width or '' }}</td>
|
<td class="table-warning">{{ placeholder.device.width or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Height:</th>
|
<th scope="row">Height:</th>
|
||||||
<td class="table-success">{{ device.height or '' }}</td>
|
<td class="table-success">{{ placeholder.binding.height or '' }}</td>
|
||||||
<td class="table-danger">{{ placeholder.device.height or '' }}</td>
|
<td class="table-warning">{{ placeholder.device.height or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Depth:</th>
|
<th scope="row">Depth:</th>
|
||||||
<td class="table-success">{{ device.depth or '' }}</td>
|
<td class="table-success">{{ placeholder.binding.depth or '' }}</td>
|
||||||
<td class="table-danger">{{ placeholder.device.depth or '' }}</td>
|
<td class="table-warning">{{ placeholder.device.depth or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Color:</th>
|
<th scope="row">Color:</th>
|
||||||
<td class="table-success">{{ device.color or '' }}</td>
|
<td class="table-success">{{ placeholder.binding.color or '' }}</td>
|
||||||
<td class="table-danger">{{ placeholder.device.color or '' }}</td>
|
<td class="table-warning">{{ placeholder.device.color or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Production date:</th>
|
<th scope="row">Production date:</th>
|
||||||
<td class="table-success">{{ device.production_date or '' }}</td>
|
<td class="table-success">{{ placeholder.binding.production_date or '' }}</td>
|
||||||
<td class="table-danger">{{ placeholder.device.production_date or '' }}</td>
|
<td class="table-warning">{{ placeholder.device.production_date or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Variant:</th>
|
<th scope="row">Variant:</th>
|
||||||
<td class="table-success">{{ device.variant or '' }}</td>
|
<td class="table-success">{{ placeholder.binding.variant or '' }}</td>
|
||||||
<td class="table-danger">{{ placeholder.device.variant or '' }}</td>
|
<td class="table-warning">{{ placeholder.device.variant or '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
{% if placeholder.device.components or device.components %}
|
{% if placeholder.components %}
|
||||||
<h2>Components</h2>
|
<h2>Components</h2>
|
||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="text-center">
|
<tr class="text-center">
|
||||||
<th scope="col">Info to be Entered</th>
|
<th scope="col">Info Abstract device</th>
|
||||||
<th scope="col">Info to be Decoupled</th>
|
<th scope="col">Info Real device</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="table-success">
|
<td class="table-success">
|
||||||
{% for c in device.components %}
|
|
||||||
* {{ c.verbose_name }}<br />
|
|
||||||
{% endfor %}
|
|
||||||
</td>
|
</td>
|
||||||
<td class="table-danger text-right">
|
<td class="table-warning text-right">
|
||||||
{% for c in placeholder.device.components %}
|
{{ placeholder.components or ''}}
|
||||||
* {{ c.verbose_name }}<br />
|
|
||||||
{% endfor %}
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -139,19 +129,22 @@
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
{% if placeholder.device.manual_actions or device.manual_actions %}
|
{% if placeholder.device.manual_actions or placeholder.binding.manual_actions %}
|
||||||
<h2>Actions</h2>
|
<h2>Actions</h2>
|
||||||
|
<p>
|
||||||
|
The actions will become real device and will no longer be in the abstract
|
||||||
|
</p>
|
||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="text-center">
|
<tr class="text-center">
|
||||||
<th scope="col">Info to be Entered</th>
|
<th scope="col">Info Abstract device</th>
|
||||||
<th scope="col">Info to be Decoupled</th>
|
<th scope="col">Info Real device</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="table-success">
|
<td class="table-success">
|
||||||
{% for a in device.manual_actions %}
|
{% for a in placeholder.binding.manual_actions %}
|
||||||
* {{ a.t }}<br />
|
* {{ a.t }}<br />
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</td>
|
</td>
|
||||||
|
@ -165,6 +158,32 @@
|
||||||
</table>
|
</table>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if placeholder.device.tags %}
|
||||||
|
<h2>Tags</h2>
|
||||||
|
<p>
|
||||||
|
The tags will become real device and will no longer be in the abstract
|
||||||
|
</p>
|
||||||
|
<table class="table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr class="text-center">
|
||||||
|
<th scope="col">Info Abstract device</th>
|
||||||
|
<th scope="col">Info Real device</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="table-success">
|
||||||
|
</td>
|
||||||
|
<td class="table-danger text-right">
|
||||||
|
{% for a in placeholder.device.tags %}
|
||||||
|
* {{ a.t }}<br />
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<form method="post">
|
<form method="post">
|
||||||
<a href="{{ url_for('inventory.device_details', id=placeholder.device.devicehub_id) }}" class="btn btn-danger">Cancel</a>
|
<a href="{{ url_for('inventory.device_details', id=placeholder.device.devicehub_id) }}" class="btn btn-danger">Cancel</a>
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -251,6 +251,7 @@ def test_update_parent():
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'action_model_state',
|
'action_model_state',
|
||||||
(
|
(
|
||||||
|
@ -264,15 +265,18 @@ def test_update_parent():
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
def test_generic_action(
|
def test_generic_action(
|
||||||
action_model_state: Tuple[models.Action, states.Trading], user: UserClient
|
action_model_state: Tuple[models.ToPrepare, states.Trading], user2: UserClient
|
||||||
):
|
):
|
||||||
"""Tests POSTing all generic actions."""
|
"""Tests POSTing all generic actions."""
|
||||||
|
user = user2
|
||||||
action_model, state = action_model_state
|
action_model, state = action_model_state
|
||||||
snapshot, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
snapshot, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
||||||
action = {'type': action_model.t, 'devices': [snapshot['device']['id']]}
|
abstract = Device.query.filter(Device.id == snapshot['device']['id']).one()
|
||||||
|
real = abstract.binding.device
|
||||||
|
action = {'type': action_model.t, 'devices': [real.id]}
|
||||||
action, _ = user.post(action, res=models.Action)
|
action, _ = user.post(action, res=models.Action)
|
||||||
assert action['devices'][0]['id'] == snapshot['device']['id']
|
assert action['devices'][0]['id'] == real.id
|
||||||
device, _ = user.get(res=Device, item=snapshot['device']['devicehubID'])
|
device, _ = user.get(res=Device, item=real.dhid)
|
||||||
assert device['actions'][-1]['id'] == action['id']
|
assert device['actions'][-1]['id'] == action['id']
|
||||||
assert device['physical'] == state.name
|
assert device['physical'] == state.name
|
||||||
# Check if the update of device is changed
|
# Check if the update of device is changed
|
||||||
|
@ -280,6 +284,7 @@ def test_generic_action(
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'action_model',
|
'action_model',
|
||||||
(
|
(
|
||||||
|
@ -288,14 +293,17 @@ def test_generic_action(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
def test_simple_status_actions(
|
def test_simple_status_actions(
|
||||||
action_model: models.Action, user: UserClient, user2: UserClient
|
action_model: models.Action, user2: UserClient
|
||||||
):
|
):
|
||||||
"""Simple test of status action."""
|
"""Simple test of status action."""
|
||||||
|
user = user2
|
||||||
snap, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
snap, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
||||||
|
abstract = Device.query.filter(Device.id == snap['device']['id']).one()
|
||||||
|
real = abstract.binding.device
|
||||||
|
|
||||||
action = {'type': action_model.t, 'devices': [snap['device']['id']]}
|
action = {'type': action_model.t, 'devices': [real.id]}
|
||||||
action, _ = user.post(action, res=models.Action)
|
action, _ = user.post(action, res=models.Action)
|
||||||
device, _ = user.get(res=Device, item=snap['device']['devicehubID'])
|
device, _ = user.get(res=Device, item=real.dhid)
|
||||||
assert device['actions'][-1]['id'] == action['id']
|
assert device['actions'][-1]['id'] == action['id']
|
||||||
assert action['author']['id'] == user.user['id']
|
assert action['author']['id'] == user.user['id']
|
||||||
assert action['rol_user']['id'] == user.user['id']
|
assert action['rol_user']['id'] == user.user['id']
|
||||||
|
@ -518,6 +526,7 @@ def test_recycling_container(user: UserClient):
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'action_model',
|
'action_model',
|
||||||
(
|
(
|
||||||
|
@ -528,13 +537,16 @@ def test_recycling_container(user: UserClient):
|
||||||
def test_status_without_lot(action_model: models.Action, user: UserClient):
|
def test_status_without_lot(action_model: models.Action, user: UserClient):
|
||||||
"""Test of status actions for devices without lot."""
|
"""Test of status actions for devices without lot."""
|
||||||
snap, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
snap, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
||||||
action = {'type': action_model.t, 'devices': [snap['device']['id']]}
|
abstract = Device.query.filter_by(id=snap['device']['id']).first()
|
||||||
|
device_id = abstract.binding.device.id
|
||||||
|
action = {'type': action_model.t, 'devices': [device_id]}
|
||||||
action, _ = user.post(action, res=models.Action)
|
action, _ = user.post(action, res=models.Action)
|
||||||
device, _ = user.get(res=Device, item=snap['device']['devicehubID'])
|
device, _ = user.get(res=Device, item=abstract.dhid)
|
||||||
assert device['actions'][-1]['id'] == action['id']
|
assert device['actions'][-1]['id'] == action['id']
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'action_model',
|
'action_model',
|
||||||
(
|
(
|
||||||
|
@ -542,17 +554,18 @@ def test_status_without_lot(action_model: models.Action, user: UserClient):
|
||||||
for ams in [models.Recycling, models.Use, models.Refurbish, models.Management]
|
for ams in [models.Recycling, models.Use, models.Refurbish, models.Management]
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
def test_status_in_temporary_lot(action_model: models.Action, user: UserClient):
|
def test_status_in_temporary_lot(action_model: models.Action, user: UserClient, app: Devicehub):
|
||||||
"""Test of status actions for devices in a temporary lot."""
|
"""Test of status actions for devices in a temporary lot."""
|
||||||
snap, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
snap, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
||||||
device_id = snap['device']['id']
|
abstract = Device.query.filter_by(id=snap['device']['id']).first()
|
||||||
|
device_id = abstract.binding.device.id
|
||||||
lot, _ = user.post({'name': 'MyLotOut'}, res=Lot)
|
lot, _ = user.post({'name': 'MyLotOut'}, res=Lot)
|
||||||
lot, _ = user.post(
|
lot, _ = user.post(
|
||||||
{}, res=Lot, item='{}/devices'.format(lot['id']), query=[('id', device_id)]
|
{}, res=Lot, item='{}/devices'.format(lot['id']), query=[('id', device_id)]
|
||||||
)
|
)
|
||||||
action = {'type': action_model.t, 'devices': [device_id]}
|
action = {'type': action_model.t, 'devices': [device_id]}
|
||||||
action, _ = user.post(action, res=models.Action)
|
action, _ = user.post(action, res=models.Action)
|
||||||
device, _ = user.get(res=Device, item=snap['device']['devicehubID'])
|
device, _ = user.get(res=Device, item=abstract.dhid)
|
||||||
assert device['actions'][-1]['id'] == action['id']
|
assert device['actions'][-1]['id'] == action['id']
|
||||||
|
|
||||||
|
|
||||||
|
@ -991,8 +1004,9 @@ def test_licences(client: Client):
|
||||||
def test_allocate(user: UserClient):
|
def test_allocate(user: UserClient):
|
||||||
"""Tests allocate"""
|
"""Tests allocate"""
|
||||||
snapshot, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
snapshot, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
||||||
device_id = snapshot['device']['id']
|
abstract = Device.query.filter_by(id=snapshot['device']['id']).one()
|
||||||
devicehub_id = snapshot['device']['devicehubID']
|
device_id = abstract.binding.device.id
|
||||||
|
devicehub_id = abstract.dhid
|
||||||
post_request = {
|
post_request = {
|
||||||
"transaction": "ccc",
|
"transaction": "ccc",
|
||||||
"finalUserCode": "aabbcc",
|
"finalUserCode": "aabbcc",
|
||||||
|
@ -1060,8 +1074,9 @@ def test_allocate_bad_dates(user: UserClient):
|
||||||
def test_deallocate(user: UserClient):
|
def test_deallocate(user: UserClient):
|
||||||
"""Tests deallocate"""
|
"""Tests deallocate"""
|
||||||
snapshot, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
snapshot, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
||||||
device_id = snapshot['device']['id']
|
abstract = Device.query.filter_by(id=snapshot['device']['id']).one()
|
||||||
devicehub_id = snapshot['device']['devicehubID']
|
device_id = abstract.binding.device.id
|
||||||
|
devicehub_id = abstract.dhid
|
||||||
post_deallocate = {
|
post_deallocate = {
|
||||||
"startTime": "2020-11-01T02:00:00+00:00",
|
"startTime": "2020-11-01T02:00:00+00:00",
|
||||||
"transaction": "ccc",
|
"transaction": "ccc",
|
||||||
|
@ -1393,27 +1408,6 @@ def test_price_custom():
|
||||||
assert c['price']['id'] == p['id']
|
assert c['price']['id'] == p['id']
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
|
||||||
def test_price_custom_client(user: UserClient):
|
|
||||||
"""As test_price_custom but creating the price through the API."""
|
|
||||||
s = file('basic.snapshot')
|
|
||||||
snapshot, _ = user.post(s, res=models.Snapshot)
|
|
||||||
price, _ = user.post(
|
|
||||||
{
|
|
||||||
'type': 'Price',
|
|
||||||
'price': 25,
|
|
||||||
'currency': Currency.EUR.name,
|
|
||||||
'device': snapshot['device']['id'],
|
|
||||||
},
|
|
||||||
res=models.Action,
|
|
||||||
)
|
|
||||||
assert 25 == price['price']
|
|
||||||
assert Currency.EUR.name == price['currency']
|
|
||||||
|
|
||||||
device, _ = user.get(res=Device, item=price['device']['devicehubID'])
|
|
||||||
assert 25 == device['price']['price']
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
||||||
def test_erase_physical():
|
def test_erase_physical():
|
||||||
|
|
|
@ -54,6 +54,7 @@ def test_api_docs(client: Client):
|
||||||
'/inventory/device/',
|
'/inventory/device/',
|
||||||
'/inventory/device/add/',
|
'/inventory/device/add/',
|
||||||
'/inventory/device/{id}/',
|
'/inventory/device/{id}/',
|
||||||
|
'/inventory/device/{dhid}/binding/',
|
||||||
'/inventory/export/{export_id}/',
|
'/inventory/export/{export_id}/',
|
||||||
'/inventory/lot/add/',
|
'/inventory/lot/add/',
|
||||||
'/inventory/lot/{id}/',
|
'/inventory/lot/{id}/',
|
||||||
|
@ -68,8 +69,8 @@ def test_api_docs(client: Client):
|
||||||
'/inventory/lot/{lot_id}/upload-snapshot/',
|
'/inventory/lot/{lot_id}/upload-snapshot/',
|
||||||
'/inventory/snapshots/{snapshot_uuid}/',
|
'/inventory/snapshots/{snapshot_uuid}/',
|
||||||
'/inventory/snapshots/',
|
'/inventory/snapshots/',
|
||||||
'/inventory/tag/devices/add/',
|
'/inventory/tag/devices/{dhid}/add/',
|
||||||
'/inventory/tag/devices/{id}/del/',
|
'/inventory/tag/devices/{dhid}/del/',
|
||||||
'/inventory/upload-snapshot/',
|
'/inventory/upload-snapshot/',
|
||||||
'/inventory/device/edit/{id}/',
|
'/inventory/device/edit/{id}/',
|
||||||
'/inventory/upload-placeholder/',
|
'/inventory/upload-placeholder/',
|
||||||
|
|
|
@ -473,6 +473,7 @@ def test_get_devices(app: Devicehub, user: UserClient):
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
def test_get_device_permissions(app: Devicehub, user: UserClient, user2: UserClient,
|
def test_get_device_permissions(app: Devicehub, user: UserClient, user2: UserClient,
|
||||||
client: Client):
|
client: Client):
|
||||||
"""Checks GETting a d.Desktop with its components."""
|
"""Checks GETting a d.Desktop with its components."""
|
||||||
|
@ -480,7 +481,9 @@ def test_get_device_permissions(app: Devicehub, user: UserClient, user2: UserCli
|
||||||
s, _ = user.post(file('asus-eee-1000h.snapshot.11'), res=m.Snapshot)
|
s, _ = user.post(file('asus-eee-1000h.snapshot.11'), res=m.Snapshot)
|
||||||
pc, res = user.get(res=d.Device, item=s['device']['devicehubID'])
|
pc, res = user.get(res=d.Device, item=s['device']['devicehubID'])
|
||||||
assert res.status_code == 200
|
assert res.status_code == 200
|
||||||
assert len(pc['actions']) == 7
|
assert len(pc['actions']) == 0
|
||||||
|
pc = d.Device.query.filter_by(devicehub_id=s['device']['devicehubID']).one()
|
||||||
|
assert len(pc.placeholder.binding.actions) == 7
|
||||||
|
|
||||||
html, _ = client.get(res=d.Device, item=s['device']['devicehubID'], accept=ANY)
|
html, _ = client.get(res=d.Device, item=s['device']['devicehubID'], accept=ANY)
|
||||||
assert 'intel atom cpu n270 @ 1.60ghz' in html
|
assert 'intel atom cpu n270 @ 1.60ghz' in html
|
||||||
|
@ -660,12 +663,15 @@ def test_cooking_mixer_api(user: UserClient):
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
def test_hid_with_mac(app: Devicehub, user: UserClient):
|
def test_hid_with_mac(app: Devicehub, user: UserClient):
|
||||||
"""Checks hid with mac."""
|
"""Checks hid with mac."""
|
||||||
snapshot = file('asus-eee-1000h.snapshot.11')
|
snapshot = file('asus-eee-1000h.snapshot.11')
|
||||||
snap, _ = user.post(snapshot, res=m.Snapshot)
|
snap, _ = user.post(snapshot, res=m.Snapshot)
|
||||||
pc, _ = user.get(res=d.Device, item=snap['device']['devicehubID'])
|
pc, _ = user.get(res=d.Device, item=snap['device']['devicehubID'])
|
||||||
assert pc['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
assert pc['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116'
|
||||||
|
pc = d.Device.query.filter_by(devicehub_id=snap['device']['devicehubID']).one()
|
||||||
|
assert pc.placeholder.binding.hid == 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@ -706,6 +712,7 @@ def test_hid_with_2networkadapters(app: Devicehub, user: UserClient):
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
def test_hid_with_2network_and_drop_no_mac_in_hid(app: Devicehub, user: UserClient):
|
def test_hid_with_2network_and_drop_no_mac_in_hid(app: Devicehub, user: UserClient):
|
||||||
"""Checks hid with 2 networks adapters and next drop the network is not used in hid"""
|
"""Checks hid with 2 networks adapters and next drop the network is not used in hid"""
|
||||||
snapshot = yaml2json('asus-eee-1000h.snapshot.11')
|
snapshot = yaml2json('asus-eee-1000h.snapshot.11')
|
||||||
|
@ -715,19 +722,22 @@ def test_hid_with_2network_and_drop_no_mac_in_hid(app: Devicehub, user: UserClie
|
||||||
network['serialNumber'] = 'a0:24:8c:7f:cf:2d'
|
network['serialNumber'] = 'a0:24:8c:7f:cf:2d'
|
||||||
snap, _ = user.post(json_encode(snapshot), res=m.Snapshot)
|
snap, _ = user.post(json_encode(snapshot), res=m.Snapshot)
|
||||||
pc, _ = user.get(res=d.Device, item=snap['device']['devicehubID'])
|
pc, _ = user.get(res=d.Device, item=snap['device']['devicehubID'])
|
||||||
assert pc['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
assert pc['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116'
|
||||||
|
pc = d.Device.query.filter_by(devicehub_id=snap['device']['devicehubID']).one()
|
||||||
|
assert pc.placeholder.binding.hid == 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
||||||
|
|
||||||
snapshot['uuid'] = 'd1b70cb8-8929-4f36-99b7-fe052cec0abb'
|
snapshot['uuid'] = 'd1b70cb8-8929-4f36-99b7-fe052cec0abb'
|
||||||
snapshot['components'] = [c for c in snapshot['components'] if c != network]
|
snapshot['components'] = [c for c in snapshot['components'] if c != network]
|
||||||
user.post(json_encode(snapshot), res=m.Snapshot)
|
user.post(json_encode(snapshot), res=m.Snapshot)
|
||||||
devices, _ = user.get(res=d.Device)
|
devices, _ = user.get(res=d.Device)
|
||||||
laptop = devices['items'][0]
|
laptop = devices['items'][0]
|
||||||
assert laptop['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
assert pc.placeholder.binding.hid == 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
||||||
assert len([c for c in devices['items'] if c['type'] == 'Laptop']) == 2
|
assert len([c for c in devices['items'] if c['type'] == 'Laptop']) == 2
|
||||||
assert len([c for c in laptop['components'] if c['type'] == 'NetworkAdapter']) == 1
|
assert len([c for c in laptop['components'] if c['type'] == 'NetworkAdapter']) == 1
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
def test_hid_with_2network_and_drop_mac_in_hid(app: Devicehub, user: UserClient):
|
def test_hid_with_2network_and_drop_mac_in_hid(app: Devicehub, user: UserClient):
|
||||||
"""Checks hid with 2 networks adapters and next drop the network is used in hid"""
|
"""Checks hid with 2 networks adapters and next drop the network is used in hid"""
|
||||||
# One tipical snapshot with 2 network cards
|
# One tipical snapshot with 2 network cards
|
||||||
|
@ -738,7 +748,9 @@ def test_hid_with_2network_and_drop_mac_in_hid(app: Devicehub, user: UserClient)
|
||||||
network['serialNumber'] = 'a0:24:8c:7f:cf:2d'
|
network['serialNumber'] = 'a0:24:8c:7f:cf:2d'
|
||||||
snap, _ = user.post(json_encode(snapshot), res=m.Snapshot)
|
snap, _ = user.post(json_encode(snapshot), res=m.Snapshot)
|
||||||
pc, _ = user.get(res=d.Device, item=snap['device']['devicehubID'])
|
pc, _ = user.get(res=d.Device, item=snap['device']['devicehubID'])
|
||||||
assert pc['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
assert pc['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116'
|
||||||
|
pc = d.Device.query.filter_by(devicehub_id=snap['device']['devicehubID']).one()
|
||||||
|
assert pc.placeholder.binding.hid == 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
||||||
|
|
||||||
# we drop the network card then is used for to build the hid
|
# we drop the network card then is used for to build the hid
|
||||||
snapshot['uuid'] = 'd1b70cb8-8929-4f36-99b7-fe052cec0abb'
|
snapshot['uuid'] = 'd1b70cb8-8929-4f36-99b7-fe052cec0abb'
|
||||||
|
|
|
@ -238,18 +238,22 @@ def test_device_search_regenerate_table(app: DeviceSearch, user: UserClient):
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
def test_device_query_search(user: UserClient):
|
def test_device_query_search(user: UserClient):
|
||||||
# todo improve
|
# todo improve
|
||||||
snapshot, _ = user.post(file('basic.snapshot'), res=Snapshot)
|
snapshot, _ = user.post(file('basic.snapshot'), res=Snapshot)
|
||||||
|
dev = Device.query.filter_by(id=snapshot['device']['id']).one()
|
||||||
user.post(file('computer-monitor.snapshot'), res=Snapshot)
|
user.post(file('computer-monitor.snapshot'), res=Snapshot)
|
||||||
user.post(file('real-eee-1001pxd.snapshot.11'), res=Snapshot)
|
user.post(file('real-eee-1001pxd.snapshot.11'), res=Snapshot)
|
||||||
i, _ = user.get(res=Device, query=[('search', 'desktop')])
|
i, _ = user.get(res=Device, query=[('search', 'desktop')])
|
||||||
assert i['items'][0]['id'] == snapshot['device']['id']
|
assert i['items'][0]['id'] == dev.id
|
||||||
i, _ = user.get(res=Device, query=[('search', 'intel')])
|
i, _ = user.get(res=Device, query=[('search', 'intel')])
|
||||||
assert len(i['items']) == 1
|
assert len(i['items']) == 1
|
||||||
i, _ = user.get(res=Device, query=[('search', i['items'][0]['devicehubID'])])
|
dev1 = Device.query.filter_by(id=i['items'][0]['id']).one()
|
||||||
|
i, _ = user.get(res=Device, query=[('search', dev1.devicehub_id)])
|
||||||
assert len(i['items']) == 1
|
assert len(i['items']) == 1
|
||||||
i, _ = user.get(res=Device, query=[('search', snapshot['device']['id'])])
|
dev2 = Device.query.filter_by(id=i['items'][0]['id']).one()
|
||||||
|
i, _ = user.get(res=Device, query=[('search', dev2.devicehub_id)])
|
||||||
assert len(i['items']) == 1
|
assert len(i['items']) == 1
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -320,16 +320,16 @@ def test_link_tag_to_device(user3: UserClientFlask):
|
||||||
}
|
}
|
||||||
user3.post(uri, data=data)
|
user3.post(uri, data=data)
|
||||||
|
|
||||||
body, status = user3.get('/inventory/device/')
|
body, status = user3.get('/inventory/device/{}/'.format(dev.dhid))
|
||||||
assert "tag1" in body
|
assert "tag1" in body
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'tag': "tag1",
|
'tag': "tag1",
|
||||||
'device': dev.id,
|
'device': dev.dhid,
|
||||||
'csrf_token': generate_csrf(),
|
'csrf_token': generate_csrf(),
|
||||||
}
|
}
|
||||||
|
|
||||||
uri = '/inventory/tag/devices/add/'
|
uri = '/inventory/tag/devices/{}/add/'.format(dev.dhid)
|
||||||
user3.post(uri, data=data)
|
user3.post(uri, data=data)
|
||||||
assert len(list(dev.tags)) == 1
|
assert len(list(dev.tags)) == 1
|
||||||
tags = [tag.id for tag in dev.tags]
|
tags = [tag.id for tag in dev.tags]
|
||||||
|
@ -406,7 +406,7 @@ def test_print_labels(user3: UserClientFlask):
|
||||||
'csrf_token': generate_csrf(),
|
'csrf_token': generate_csrf(),
|
||||||
}
|
}
|
||||||
|
|
||||||
uri = '/inventory/tag/devices/add/'
|
uri = '/inventory/tag/devices/{}/add/'.format(dev.dhid)
|
||||||
user3.post(uri, data=data)
|
user3.post(uri, data=data)
|
||||||
|
|
||||||
assert len(list(dev.tags)) == 1
|
assert len(list(dev.tags)) == 1
|
||||||
|
@ -419,7 +419,7 @@ def test_print_labels(user3: UserClientFlask):
|
||||||
body, status = user3.post(uri, data=data)
|
body, status = user3.post(uri, data=data)
|
||||||
|
|
||||||
assert status == '200 OK'
|
assert status == '200 OK'
|
||||||
path = "/inventory/device/{}/".format(dev.devicehub_id)
|
path = "/devices/{}".format(dev.dhid)
|
||||||
assert path in body
|
assert path in body
|
||||||
assert "tag1" in body
|
assert "tag1" in body
|
||||||
|
|
||||||
|
@ -2021,7 +2021,6 @@ def test_manual_binding(user3: UserClientFlask):
|
||||||
'model': "LC27T55",
|
'model': "LC27T55",
|
||||||
'manufacturer': "Samsung",
|
'manufacturer': "Samsung",
|
||||||
'generation': 1,
|
'generation': 1,
|
||||||
'weight': 0.1,
|
|
||||||
'height': 0.1,
|
'height': 0.1,
|
||||||
'depth': 0.1,
|
'depth': 0.1,
|
||||||
'id_device_supplier': "b2",
|
'id_device_supplier': "b2",
|
||||||
|
@ -2047,17 +2046,24 @@ def test_manual_binding(user3: UserClientFlask):
|
||||||
old_placeholder = dev_wb.binding
|
old_placeholder = dev_wb.binding
|
||||||
|
|
||||||
# page binding
|
# page binding
|
||||||
dhid = dev_wb.devicehub_id
|
dhid = dev_wb.dhid
|
||||||
uri = f'/inventory/binding/{dhid}/sid/'
|
uri = f'/inventory/binding/{dhid}/sid/'
|
||||||
body, status = user3.get(uri)
|
body, status = user3.get(uri)
|
||||||
assert status == '200 OK'
|
assert status == '200 OK'
|
||||||
assert 'sid' in body
|
assert 'sid' in body
|
||||||
assert 'Confirm' in body
|
assert 'Confirm' in body
|
||||||
|
|
||||||
|
phid_real = dev.placeholder.phid
|
||||||
|
phid_abstract = dev_wb.binding.phid
|
||||||
|
dhid_real = dev.dhid
|
||||||
|
dhid_abstract = dev_wb.dhid
|
||||||
|
|
||||||
# action binding
|
# action binding
|
||||||
body, status = user3.post(uri, data={})
|
body, status = user3.post(uri, data={})
|
||||||
assert status == '200 OK'
|
assert status == '200 OK'
|
||||||
assert f"Device "{dhid}" bind successfully with sid!" in body
|
txt = f"Device real with PHID: {phid_real} and DHID: {dhid_real} "
|
||||||
|
txt += f"bind successfully with device abstract PHID: {phid_abstract} DHID: {dhid_abstract}."
|
||||||
|
assert txt in body
|
||||||
|
|
||||||
# check new structure
|
# check new structure
|
||||||
assert dev_wb.binding.phid == 'sid'
|
assert dev_wb.binding.phid == 'sid'
|
||||||
|
@ -2145,7 +2151,7 @@ def test_unbinding(user3: UserClientFlask):
|
||||||
old_placeholder = dev_wb.binding
|
old_placeholder = dev_wb.binding
|
||||||
|
|
||||||
# page binding
|
# page binding
|
||||||
dhid = dev_wb.devicehub_id
|
dhid = dev_wb.dhid
|
||||||
uri = f'/inventory/binding/{dhid}/sid/'
|
uri = f'/inventory/binding/{dhid}/sid/'
|
||||||
user3.get(uri)
|
user3.get(uri)
|
||||||
|
|
||||||
|
@ -2154,11 +2160,14 @@ def test_unbinding(user3: UserClientFlask):
|
||||||
user3.post(uri, data={})
|
user3.post(uri, data={})
|
||||||
assert dev.placeholder.binding == dev_wb
|
assert dev.placeholder.binding == dev_wb
|
||||||
|
|
||||||
|
dhid = dev.dhid
|
||||||
# action unbinding
|
# action unbinding
|
||||||
uri = '/inventory/unbinding/sid/'
|
uri = '/inventory/unbinding/sid/'
|
||||||
body, status = user3.post(uri, data={})
|
body, status = user3.post(uri, data={})
|
||||||
assert status == '200 OK'
|
assert status == '200 OK'
|
||||||
assert 'Device "sid" unbind successfully!' in body
|
txt = f'Device with PHID:"sid" and DHID: {dhid} unbind successfully!'
|
||||||
|
assert txt in body
|
||||||
|
# assert 'Device "sid" unbind successfully!' in body
|
||||||
|
|
||||||
# check new structure
|
# check new structure
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ from ereuse_devicehub.resources.action.models import (
|
||||||
from ereuse_devicehub.resources.action.views.snapshot import save_json
|
from ereuse_devicehub.resources.action.views.snapshot import save_json
|
||||||
from ereuse_devicehub.resources.device import models as m
|
from ereuse_devicehub.resources.device import models as m
|
||||||
from ereuse_devicehub.resources.device.exceptions import NeedsId
|
from ereuse_devicehub.resources.device.exceptions import NeedsId
|
||||||
from ereuse_devicehub.resources.device.models import SolidStateDrive
|
from ereuse_devicehub.resources.device.models import SolidStateDrive, Device
|
||||||
from ereuse_devicehub.resources.device.sync import (
|
from ereuse_devicehub.resources.device.sync import (
|
||||||
MismatchBetweenProperties,
|
MismatchBetweenProperties,
|
||||||
MismatchBetweenTagsAndHid,
|
MismatchBetweenTagsAndHid,
|
||||||
|
@ -91,6 +91,7 @@ def test_snapshot_schema(app: Devicehub):
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
def test_snapshot_post(user: UserClient):
|
def test_snapshot_post(user: UserClient):
|
||||||
"""Tests the post snapshot endpoint (validation, etc), data correctness,
|
"""Tests the post snapshot endpoint (validation, etc), data correctness,
|
||||||
and relationship correctness.
|
and relationship correctness.
|
||||||
|
@ -108,11 +109,12 @@ def test_snapshot_post(user: UserClient):
|
||||||
assert snapshot['author']['id'] == user.user['id']
|
assert snapshot['author']['id'] == user.user['id']
|
||||||
assert 'actions' not in snapshot['device']
|
assert 'actions' not in snapshot['device']
|
||||||
assert 'author' not in snapshot['device']
|
assert 'author' not in snapshot['device']
|
||||||
device, _ = user.get(res=m.Device, item=snapshot['device']['devicehubID'])
|
dev = m.Device.query.filter_by(id=snapshot['device']['id']).one()
|
||||||
|
device, _ = user.get(res=m.Device, item=dev.devicehub_id)
|
||||||
key = itemgetter('serialNumber')
|
key = itemgetter('serialNumber')
|
||||||
snapshot['components'].sort(key=key)
|
snapshot['components'].sort(key=key)
|
||||||
device['components'].sort(key=key)
|
device['components'].sort(key=key)
|
||||||
assert snapshot['components'] == device['components']
|
assert {(x['id'], x['type']) for x in device['components']} == {(x['id'], x['type']) for x in snapshot['components']}
|
||||||
|
|
||||||
assert {c['type'] for c in snapshot['components']} == {
|
assert {c['type'] for c in snapshot['components']} == {
|
||||||
m.GraphicCard.t,
|
m.GraphicCard.t,
|
||||||
|
@ -190,7 +192,6 @@ def test_snapshot_power_on_hours(user: UserClient):
|
||||||
)
|
)
|
||||||
|
|
||||||
errors = SnapshotsLog.query.filter().all()
|
errors = SnapshotsLog.query.filter().all()
|
||||||
snap_log = errors[1]
|
|
||||||
assert len(errors) == 2
|
assert len(errors) == 2
|
||||||
assert str(errors[0].snapshot_uuid) == snap['uuid']
|
assert str(errors[0].snapshot_uuid) == snap['uuid']
|
||||||
assert str(errors[1].snapshot.uuid) == snap['uuid']
|
assert str(errors[1].snapshot.uuid) == snap['uuid']
|
||||||
|
@ -199,6 +200,7 @@ def test_snapshot_power_on_hours(user: UserClient):
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
def test_snapshot_component_add_remove(user: UserClient):
|
def test_snapshot_component_add_remove(user: UserClient):
|
||||||
"""Tests adding and removing components and some don't generate HID.
|
"""Tests adding and removing components and some don't generate HID.
|
||||||
All computers generate HID.
|
All computers generate HID.
|
||||||
|
@ -221,7 +223,8 @@ def test_snapshot_component_add_remove(user: UserClient):
|
||||||
# RateComputer.t),
|
# RateComputer.t),
|
||||||
# perform_second_snapshot=False)
|
# perform_second_snapshot=False)
|
||||||
pc1_id = snapshot1['device']['id']
|
pc1_id = snapshot1['device']['id']
|
||||||
pc1_devicehub_id = snapshot1['device']['devicehubID']
|
pc1_dev = m.Device.query.filter_by(id=pc1_id).one()
|
||||||
|
pc1_devicehub_id = pc1_dev.devicehub_id
|
||||||
pc1, _ = user.get(res=m.Device, item=pc1_devicehub_id)
|
pc1, _ = user.get(res=m.Device, item=pc1_devicehub_id)
|
||||||
update1_pc1 = pc1['updated']
|
update1_pc1 = pc1['updated']
|
||||||
# Parent contains components
|
# Parent contains components
|
||||||
|
@ -229,14 +232,15 @@ def test_snapshot_component_add_remove(user: UserClient):
|
||||||
'p1c1s',
|
'p1c1s',
|
||||||
'p1c2s',
|
'p1c2s',
|
||||||
'p1c3s',
|
'p1c3s',
|
||||||
)
|
) == tuple(x.serial_number for x in pc1_dev.binding.device.components)
|
||||||
# Components contain parent
|
# Components contain parent
|
||||||
assert all(c['parent'] == pc1_id for c in pc1['components'])
|
assert all(c['parent'] == pc1_id for c in pc1['components'])
|
||||||
# pc has three actions: Snapshot, BenchmarkProcessor and RateComputer
|
# pc has three actions: Snapshot, BenchmarkProcessor and RateComputer
|
||||||
assert len(pc1['actions']) == 2
|
assert len(pc1['actions']) == 2
|
||||||
assert pc1['actions'][1]['type'] == Snapshot.t
|
assert pc1['actions'][1]['type'] == Snapshot.t
|
||||||
# p1c1s has Snapshot
|
# p1c1s has Snapshot
|
||||||
p1c1s, _ = user.get(res=m.Device, item=pc1['components'][0]['devicehubID'])
|
p1c1s_dev = m.Device.query.filter_by(id=pc1['components'][0]['id']).one()
|
||||||
|
p1c1s, _ = user.get(res=m.Device, item=p1c1s_dev.devicehub_id)
|
||||||
assert tuple(e['type'] for e in p1c1s['actions']) == ('Snapshot',)
|
assert tuple(e['type'] for e in p1c1s['actions']) == ('Snapshot',)
|
||||||
|
|
||||||
# We register a new device
|
# We register a new device
|
||||||
|
@ -249,7 +253,8 @@ def test_snapshot_component_add_remove(user: UserClient):
|
||||||
# snapshot2 = snapshot_and_check(user, s2, action_types=('Remove', 'RateComputer'),
|
# snapshot2 = snapshot_and_check(user, s2, action_types=('Remove', 'RateComputer'),
|
||||||
# perform_second_snapshot=False)
|
# perform_second_snapshot=False)
|
||||||
pc2_id = snapshot2['device']['id']
|
pc2_id = snapshot2['device']['id']
|
||||||
pc2_devicehub_id = snapshot2['device']['devicehubID']
|
pc2_dev = m.Device.query.filter_by(id=pc2_id).one()
|
||||||
|
pc2_devicehub_id = pc2_dev.devicehub_id
|
||||||
pc1, _ = user.get(res=m.Device, item=pc1_devicehub_id)
|
pc1, _ = user.get(res=m.Device, item=pc1_devicehub_id)
|
||||||
pc2, _ = user.get(res=m.Device, item=pc2_devicehub_id)
|
pc2, _ = user.get(res=m.Device, item=pc2_devicehub_id)
|
||||||
# Check if the update_timestamp is updated
|
# Check if the update_timestamp is updated
|
||||||
|
@ -269,7 +274,8 @@ def test_snapshot_component_add_remove(user: UserClient):
|
||||||
assert all(c['parent'] == pc2_id for c in pc2['components'])
|
assert all(c['parent'] == pc2_id for c in pc2['components'])
|
||||||
assert tuple(e['type'] for e in pc2['actions']) == ('Snapshot',)
|
assert tuple(e['type'] for e in pc2['actions']) == ('Snapshot',)
|
||||||
# p1c2s has two Snapshots, a Remove and an Add
|
# p1c2s has two Snapshots, a Remove and an Add
|
||||||
p1c2s, _ = user.get(res=m.Device, item=pc2['components'][0]['devicehubID'])
|
p1c2s_dev = m.Device.query.filter_by(id=pc2['components'][0]['id']).one()
|
||||||
|
p1c2s, _ = user.get(res=m.Device, item=p1c2s_dev.devicehub_id)
|
||||||
assert tuple(e['type'] for e in p1c2s['actions']) == (
|
assert tuple(e['type'] for e in p1c2s['actions']) == (
|
||||||
'BenchmarkProcessor',
|
'BenchmarkProcessor',
|
||||||
'Snapshot',
|
'Snapshot',
|
||||||
|
@ -299,8 +305,8 @@ def test_snapshot_component_add_remove(user: UserClient):
|
||||||
assert tuple(get_actions_info(pc1['actions'])) == (
|
assert tuple(get_actions_info(pc1['actions'])) == (
|
||||||
# id, type, components, snapshot
|
# id, type, components, snapshot
|
||||||
('BenchmarkProcessor', []), # first BenchmarkProcessor
|
('BenchmarkProcessor', []), # first BenchmarkProcessor
|
||||||
('Snapshot', ['p1c1s', 'p1c2s', 'p1c3s']), # first Snapshot1
|
('Snapshot', ['p1c1s', 'p1c2s', 'p1c3s', 'p1c2s']), # first Snapshot1
|
||||||
('Remove', ['p1c2s']), # Remove Processor in Snapshot2
|
('Remove', ['p1c2s', 'p1c2s']), # Remove Processor in Snapshot2
|
||||||
('Snapshot', ['p1c2s', 'p1c3s']), # This Snapshot3
|
('Snapshot', ['p1c2s', 'p1c3s']), # This Snapshot3
|
||||||
)
|
)
|
||||||
# PC2
|
# PC2
|
||||||
|
@ -311,12 +317,13 @@ def test_snapshot_component_add_remove(user: UserClient):
|
||||||
'Remove', # the processor we added in 2.
|
'Remove', # the processor we added in 2.
|
||||||
)
|
)
|
||||||
# p1c2s has Snapshot, Remove and Add
|
# p1c2s has Snapshot, Remove and Add
|
||||||
p1c2s, _ = user.get(res=m.Device, item=pc1['components'][0]['devicehubID'])
|
p1c2s_dev = m.Device.query.filter_by(id=pc1['components'][0]['id']).one()
|
||||||
|
p1c2s, _ = user.get(res=m.Device, item=p1c2s_dev.devicehub_id)
|
||||||
assert tuple(get_actions_info(p1c2s['actions'])) == (
|
assert tuple(get_actions_info(p1c2s['actions'])) == (
|
||||||
('BenchmarkProcessor', []), # first BenchmarkProcessor
|
('BenchmarkProcessor', []), # first BenchmarkProcessor
|
||||||
('Snapshot', ['p1c1s', 'p1c2s', 'p1c3s']), # First Snapshot to PC1
|
('Snapshot', ['p1c1s', 'p1c2s', 'p1c3s', 'p1c2s']), # First Snapshot to PC1
|
||||||
('Snapshot', ['p1c2s', 'p2c1s']), # Second Snapshot to PC2
|
('Snapshot', ['p1c2s', 'p2c1s']), # Second Snapshot to PC2
|
||||||
('Remove', ['p1c2s']), # ...which caused p1c2s to be removed form PC1
|
('Remove', ['p1c2s', 'p1c2s']), # ...which caused p1c2s to be removed form PC1
|
||||||
('Snapshot', ['p1c2s', 'p1c3s']), # The third Snapshot to PC1
|
('Snapshot', ['p1c2s', 'p1c3s']), # The third Snapshot to PC1
|
||||||
('Remove', ['p1c2s']), # ...which caused p1c2 to be removed from PC2
|
('Remove', ['p1c2s']), # ...which caused p1c2 to be removed from PC2
|
||||||
)
|
)
|
||||||
|
@ -482,6 +489,7 @@ def test_not_remove_ram_in_same_computer(user: UserClient):
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
def test_erase_privacy_standards_endtime_sort(user: UserClient):
|
def test_erase_privacy_standards_endtime_sort(user: UserClient):
|
||||||
"""Tests a Snapshot with EraseSectors and the resulting privacy
|
"""Tests a Snapshot with EraseSectors and the resulting privacy
|
||||||
properties.
|
properties.
|
||||||
|
@ -520,8 +528,9 @@ def test_erase_privacy_standards_endtime_sort(user: UserClient):
|
||||||
|
|
||||||
# The actual test
|
# The actual test
|
||||||
storage = next(e for e in snapshot['components'] if e['type'] == SolidStateDrive.t)
|
storage = next(e for e in snapshot['components'] if e['type'] == SolidStateDrive.t)
|
||||||
|
db_storage = m.Device.query.filter_by(id=storage['id']).one()
|
||||||
storage, _ = user.get(
|
storage, _ = user.get(
|
||||||
res=m.Device, item=storage['devicehubID']
|
res=m.Device, item=db_storage.devicehub_id
|
||||||
) # Let's get storage actions too
|
) # Let's get storage actions too
|
||||||
# order: endTime ascending
|
# order: endTime ascending
|
||||||
# erasure1/2 have an user defined time and others actions endTime = created
|
# erasure1/2 have an user defined time and others actions endTime = created
|
||||||
|
@ -555,17 +564,22 @@ def test_erase_privacy_standards_endtime_sort(user: UserClient):
|
||||||
assert 'num' not in step2
|
assert 'num' not in step2
|
||||||
assert ['HMG_IS5'] == erasure['standards']
|
assert ['HMG_IS5'] == erasure['standards']
|
||||||
assert storage['privacy']['type'] == 'EraseSectors'
|
assert storage['privacy']['type'] == 'EraseSectors'
|
||||||
pc, _ = user.get(res=m.Device, item=snapshot['device']['devicehubID'])
|
dev = m.Device.query.filter_by(id=snapshot['device']['id']).one()
|
||||||
|
pc, _ = user.get(res=m.Device, item=dev.devicehub_id)
|
||||||
|
# pc, _ = user.get(res=m.Device, item=snapshot['device']['devicehubID'])
|
||||||
assert pc['privacy'] == [storage['privacy']]
|
assert pc['privacy'] == [storage['privacy']]
|
||||||
|
|
||||||
# Let's try a second erasure with an error
|
# Let's try a second erasure with an error
|
||||||
s['uuid'] = uuid4()
|
s['uuid'] = uuid4()
|
||||||
s['components'][0]['actions'][0]['severity'] = 'Error'
|
s['components'][0]['actions'][0]['severity'] = 'Error'
|
||||||
snapshot, _ = user.post(json_encode(s), res=Snapshot)
|
snapshot, _ = user.post(json_encode(s), res=Snapshot)
|
||||||
storage, _ = user.get(res=m.Device, item=storage['devicehubID'])
|
storage, _ = user.get(res=m.Device, item=db_storage.devicehub_id)
|
||||||
assert storage['hid'] == 'solidstatedrive-c1mr-c1ml-c1s'
|
assert storage['hid'] == 'solidstatedrive-c1mr-c1ml-c1s'
|
||||||
|
assert dev.components[0].privacy.type == 'EraseSectors'
|
||||||
assert storage['privacy']['type'] == 'EraseSectors'
|
assert storage['privacy']['type'] == 'EraseSectors'
|
||||||
pc, _ = user.get(res=m.Device, item=snapshot['device']['devicehubID'])
|
dev = m.Device.query.filter_by(id=snapshot['device']['id']).one()
|
||||||
|
pc, _ = user.get(res=m.Device, item=dev.devicehub_id)
|
||||||
|
# import pdb; pdb.set_trace()
|
||||||
assert pc['privacy'] == [storage['privacy']]
|
assert pc['privacy'] == [storage['privacy']]
|
||||||
|
|
||||||
|
|
||||||
|
@ -889,23 +903,26 @@ def test_snapshot_failed_missing_chassis(app: Devicehub, user: UserClient):
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
def test_snapshot_failed_end_time_bug(app: Devicehub, user: UserClient):
|
def test_snapshot_failed_end_time_bug(app: Devicehub, user: UserClient):
|
||||||
"""This test check if the end_time = 0001-01-01 00:00:00+00:00
|
"""This test check if the end_time = 0001-01-01 00:00:00+00:00
|
||||||
and then we get a /devices, this create a crash
|
and then we get a /devices, this create a crash
|
||||||
"""
|
"""
|
||||||
snapshot_file = file('asus-end_time_bug88.snapshot')
|
snapshot_file = file('asus-end_time_bug88.snapshot')
|
||||||
snapshot, _ = user.post(res=Snapshot, data=snapshot_file)
|
snapshot, _ = user.post(res=Snapshot, data=snapshot_file)
|
||||||
device, _ = user.get(res=m.Device, item=snapshot['device']['devicehubID'])
|
dev = m.Device.query.filter_by(id=snapshot['device']['id']).one()
|
||||||
|
device, _ = user.get(res=m.Device, item=dev.devicehub_id)
|
||||||
end_times = [x['endTime'] for x in device['actions']]
|
end_times = [x['endTime'] for x in device['actions']]
|
||||||
|
|
||||||
assert '1970-01-02T00:00:00+00:00' in end_times
|
assert '1970-01-02T00:00:00+00:00' in end_times
|
||||||
assert not '0001-01-01T00:00:00+00:00' in end_times
|
assert '0001-01-01T00:00:00+00:00' not in end_times
|
||||||
|
|
||||||
tmp_snapshots = app.config['TMP_SNAPSHOTS']
|
tmp_snapshots = app.config['TMP_SNAPSHOTS']
|
||||||
shutil.rmtree(tmp_snapshots)
|
shutil.rmtree(tmp_snapshots)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
def test_snapshot_not_failed_end_time_bug(app: Devicehub, user: UserClient):
|
def test_snapshot_not_failed_end_time_bug(app: Devicehub, user: UserClient):
|
||||||
"""This test check if the end_time != 0001-01-01 00:00:00+00:00
|
"""This test check if the end_time != 0001-01-01 00:00:00+00:00
|
||||||
and then we get a /devices, this create a crash
|
and then we get a /devices, this create a crash
|
||||||
|
@ -913,7 +930,8 @@ def test_snapshot_not_failed_end_time_bug(app: Devicehub, user: UserClient):
|
||||||
snapshot_file = yaml2json('asus-end_time_bug88.snapshot')
|
snapshot_file = yaml2json('asus-end_time_bug88.snapshot')
|
||||||
snapshot_file['endTime'] = '2001-01-01 00:00:00+00:00'
|
snapshot_file['endTime'] = '2001-01-01 00:00:00+00:00'
|
||||||
snapshot, _ = user.post(res=Snapshot, data=json_encode(snapshot_file))
|
snapshot, _ = user.post(res=Snapshot, data=json_encode(snapshot_file))
|
||||||
device, _ = user.get(res=m.Device, item=snapshot['device']['devicehubID'])
|
db_dev = Device.query.filter_by(id=snapshot['device']['id']).one()
|
||||||
|
device, _ = user.get(res=m.Device, item=db_dev.devicehub_id)
|
||||||
end_times = [x['endTime'] for x in device['actions']]
|
end_times = [x['endTime'] for x in device['actions']]
|
||||||
|
|
||||||
assert not '1970-01-02T00:00:00+00:00' in end_times
|
assert not '1970-01-02T00:00:00+00:00' in end_times
|
||||||
|
@ -974,6 +992,7 @@ def test_snapshot_wb_lite(user: UserClient):
|
||||||
body, res = user.post(snapshot, uri="/api/inventory/")
|
body, res = user.post(snapshot, uri="/api/inventory/")
|
||||||
|
|
||||||
dev = m.Device.query.filter_by(devicehub_id=body['dhid']).one()
|
dev = m.Device.query.filter_by(devicehub_id=body['dhid']).one()
|
||||||
|
dev = dev.placeholder.binding
|
||||||
ssd = [x for x in dev.components if x.type == 'SolidStateDrive'][0]
|
ssd = [x for x in dev.components if x.type == 'SolidStateDrive'][0]
|
||||||
|
|
||||||
assert dev.manufacturer == 'lenovo'
|
assert dev.manufacturer == 'lenovo'
|
||||||
|
@ -1000,6 +1019,7 @@ def test_snapshot_wb_lite_qemu(user: UserClient):
|
||||||
assert res.status == '201 CREATED'
|
assert res.status == '201 CREATED'
|
||||||
|
|
||||||
dev = m.Device.query.filter_by(devicehub_id=body['dhid']).one()
|
dev = m.Device.query.filter_by(devicehub_id=body['dhid']).one()
|
||||||
|
dev = dev.placeholder.binding
|
||||||
assert dev.manufacturer == 'qemu'
|
assert dev.manufacturer == 'qemu'
|
||||||
assert dev.model == 'standard'
|
assert dev.model == 'standard'
|
||||||
assert dev.serial_number is None
|
assert dev.serial_number is None
|
||||||
|
@ -1235,6 +1255,7 @@ def test_snapshot_errors(user: UserClient):
|
||||||
assert len(SnapshotsLog.query.all()) == 1
|
assert len(SnapshotsLog.query.all()) == 1
|
||||||
bodyLite, res = user.post(snapshot_lite, uri="/api/inventory/")
|
bodyLite, res = user.post(snapshot_lite, uri="/api/inventory/")
|
||||||
dev = m.Device.query.filter_by(devicehub_id=bodyLite['dhid']).one()
|
dev = m.Device.query.filter_by(devicehub_id=bodyLite['dhid']).one()
|
||||||
|
dev = dev.placeholder.binding
|
||||||
assert len(SnapshotsLog.query.all()) == 4
|
assert len(SnapshotsLog.query.all()) == 4
|
||||||
|
|
||||||
assert body11['device'].get('hid') == dev.hid
|
assert body11['device'].get('hid') == dev.hid
|
||||||
|
@ -1276,6 +1297,7 @@ def test_snapshot_errors_no_serial_number(user: UserClient):
|
||||||
assert len(logs) == 1
|
assert len(logs) == 1
|
||||||
assert logs[0].description == 'Ok'
|
assert logs[0].description == 'Ok'
|
||||||
dev = m.Device.query.filter_by(devicehub_id=bodyLite['dhid']).one()
|
dev = m.Device.query.filter_by(devicehub_id=bodyLite['dhid']).one()
|
||||||
|
dev = dev.placeholder.binding
|
||||||
assert not dev.model
|
assert not dev.model
|
||||||
assert not dev.manufacturer
|
assert not dev.manufacturer
|
||||||
assert not dev.serial_number
|
assert not dev.serial_number
|
||||||
|
|
|
@ -364,13 +364,12 @@ def test_tag_secondary_workbench_link_find(user: UserClient):
|
||||||
s = yaml2json('basic.snapshot')
|
s = yaml2json('basic.snapshot')
|
||||||
s['device']['tags'] = [{'id': 'foo', 'secondary': 'bar', 'type': 'Tag'}]
|
s['device']['tags'] = [{'id': 'foo', 'secondary': 'bar', 'type': 'Tag'}]
|
||||||
snapshot, _ = user.post(json_encode(s), res=Snapshot)
|
snapshot, _ = user.post(json_encode(s), res=Snapshot)
|
||||||
device, _ = user.get(res=Device, item=snapshot['device']['devicehubID'])
|
dev = Device.query.filter_by(id=snapshot['device']['id']).one()
|
||||||
desktop = Device.query.filter_by(
|
device, _ = user.get(res=Device, item=dev.devicehub_id)
|
||||||
devicehub_id=snapshot['device']['devicehubID']
|
desktop = dev.binding.device
|
||||||
).one()
|
|
||||||
assert [] == [x['id'] for x in device['tags']]
|
assert [] == [x['id'] for x in device['tags']]
|
||||||
assert 'foo' in [x.id for x in desktop.binding.device.tags]
|
assert 'foo' in [x.id for x in desktop.tags]
|
||||||
assert 'bar' in [x.secondary for x in desktop.binding.device.tags]
|
assert 'bar' in [x.secondary for x in desktop.tags]
|
||||||
|
|
||||||
r, _ = user.get(
|
r, _ = user.get(
|
||||||
res=Device, query=[('search', 'foo'), ('filter', {'type': ['Computer']})]
|
res=Device, query=[('search', 'foo'), ('filter', {'type': ['Computer']})]
|
||||||
|
|
|
@ -16,9 +16,11 @@ from ereuse_devicehub.resources.device.exceptions import NeedsId
|
||||||
from ereuse_devicehub.resources.device.models import Device
|
from ereuse_devicehub.resources.device.models import Device
|
||||||
from ereuse_devicehub.resources.tag.model import Tag
|
from ereuse_devicehub.resources.tag.model import Tag
|
||||||
from tests.conftest import file, file_workbench, json_encode, yaml2json
|
from tests.conftest import file, file_workbench, json_encode, yaml2json
|
||||||
|
from tests import conftest
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
def test_workbench_server_condensed(user: UserClient):
|
def test_workbench_server_condensed(user: UserClient):
|
||||||
"""As :def:`.test_workbench_server_phases` but all the actions
|
"""As :def:`.test_workbench_server_phases` but all the actions
|
||||||
condensed in only one big ``Snapshot`` file, as described
|
condensed in only one big ``Snapshot`` file, as described
|
||||||
|
@ -54,7 +56,8 @@ def test_workbench_server_condensed(user: UserClient):
|
||||||
}
|
}
|
||||||
assert snapshot['closed']
|
assert snapshot['closed']
|
||||||
assert snapshot['severity'] == 'Info'
|
assert snapshot['severity'] == 'Info'
|
||||||
device, _ = user.get(res=Device, item=snapshot['device']['devicehubID'])
|
db_dev = Device.query.filter_by(id=snapshot['device']['id']).one()
|
||||||
|
device, _ = user.get(res=Device, item=db_dev.devicehub_id)
|
||||||
assert device['dataStorageSize'] == 1100
|
assert device['dataStorageSize'] == 1100
|
||||||
assert device['chassis'] == 'Tower'
|
assert device['chassis'] == 'Tower'
|
||||||
assert device['hid'] == 'desktop-d1mr-d1ml-d1s-na1-s'
|
assert device['hid'] == 'desktop-d1mr-d1ml-d1s-na1-s'
|
||||||
|
@ -175,13 +178,15 @@ def test_real_toshiba_11(user: UserClient):
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
def test_snapshot_real_eee_1001pxd_with_rate(user: UserClient):
|
def test_snapshot_real_eee_1001pxd_with_rate(user: UserClient):
|
||||||
"""Checks the values of the device, components,
|
"""Checks the values of the device, components,
|
||||||
actions and their relationships of a real pc.
|
actions and their relationships of a real pc.
|
||||||
"""
|
"""
|
||||||
s = file('real-eee-1001pxd.snapshot.11')
|
s = file('real-eee-1001pxd.snapshot.11')
|
||||||
snapshot, _ = user.post(res=em.Snapshot, data=s)
|
snapshot, _ = user.post(res=em.Snapshot, data=s)
|
||||||
pc, _ = user.get(res=Device, item=snapshot['device']['devicehubID'])
|
dev = Device.query.filter_by(id=snapshot['device']['id']).one()
|
||||||
|
pc, _ = user.get(res=Device, item=dev.devicehub_id)
|
||||||
assert pc['type'] == 'Laptop'
|
assert pc['type'] == 'Laptop'
|
||||||
assert pc['chassis'] == 'Netbook'
|
assert pc['chassis'] == 'Netbook'
|
||||||
assert pc['model'] == '1001pxd'
|
assert pc['model'] == '1001pxd'
|
||||||
|
@ -222,7 +227,8 @@ def test_snapshot_real_eee_1001pxd_with_rate(user: UserClient):
|
||||||
assert cpu['speed'] == 1.667
|
assert cpu['speed'] == 1.667
|
||||||
assert 'hid' not in cpu
|
assert 'hid' not in cpu
|
||||||
assert pc['processorModel'] == cpu['model'] == 'intel atom cpu n455 @ 1.66ghz'
|
assert pc['processorModel'] == cpu['model'] == 'intel atom cpu n455 @ 1.66ghz'
|
||||||
cpu, _ = user.get(res=Device, item=cpu['devicehubID'])
|
db_cpu = Device.query.filter_by(id=cpu['id']).one()
|
||||||
|
cpu, _ = user.get(res=Device, item=db_cpu.devicehub_id)
|
||||||
actions = cpu['actions']
|
actions = cpu['actions']
|
||||||
sysbench = next(e for e in actions if e['type'] == em.BenchmarkProcessorSysbench.t)
|
sysbench = next(e for e in actions if e['type'] == em.BenchmarkProcessorSysbench.t)
|
||||||
assert sysbench['elapsed'] == 164
|
assert sysbench['elapsed'] == 164
|
||||||
|
@ -245,7 +251,8 @@ def test_snapshot_real_eee_1001pxd_with_rate(user: UserClient):
|
||||||
)
|
)
|
||||||
assert gpu['manufacturer'] == 'intel corporation'
|
assert gpu['manufacturer'] == 'intel corporation'
|
||||||
assert gpu['memory'] == 256
|
assert gpu['memory'] == 256
|
||||||
gpu, _ = user.get(res=Device, item=gpu['devicehubID'])
|
db_gpu = Device.query.filter_by(id=gpu['id']).one()
|
||||||
|
gpu, _ = user.get(res=Device, item=db_gpu.devicehub_id)
|
||||||
action_types = tuple(e['type'] for e in gpu['actions'])
|
action_types = tuple(e['type'] for e in gpu['actions'])
|
||||||
assert em.BenchmarkRamSysbench.t in action_types
|
assert em.BenchmarkRamSysbench.t in action_types
|
||||||
assert em.StressTest.t in action_types
|
assert em.StressTest.t in action_types
|
||||||
|
@ -264,7 +271,8 @@ def test_snapshot_real_eee_1001pxd_with_rate(user: UserClient):
|
||||||
assert hdd['hid'] == 'harddrive-hitachi-hts54322-e2024242cv86hj'
|
assert hdd['hid'] == 'harddrive-hitachi-hts54322-e2024242cv86hj'
|
||||||
assert hdd['interface'] == 'ATA'
|
assert hdd['interface'] == 'ATA'
|
||||||
assert hdd['size'] == 238475
|
assert hdd['size'] == 238475
|
||||||
hdd, _ = user.get(res=Device, item=hdd['devicehubID'])
|
db_hdd = Device.query.filter_by(id=hdd['id']).one()
|
||||||
|
hdd, _ = user.get(res=Device, item=db_hdd.devicehub_id)
|
||||||
action_types = tuple(e['type'] for e in hdd['actions'])
|
action_types = tuple(e['type'] for e in hdd['actions'])
|
||||||
assert em.BenchmarkRamSysbench.t in action_types
|
assert em.BenchmarkRamSysbench.t in action_types
|
||||||
assert em.StressTest.t in action_types
|
assert em.StressTest.t in action_types
|
||||||
|
|
Reference in New Issue