Merge pull request #327 from eReuse/feature/3598-binding
Feature/3598 binding
This commit is contained in:
commit
00f03cb082
|
@ -317,6 +317,7 @@ class NewDeviceForm(FlaskForm):
|
||||||
id_device_supplier = StringField('Id Supplier', [validators.Optional()])
|
id_device_supplier = StringField('Id Supplier', [validators.Optional()])
|
||||||
phid = StringField('Placeholder Hardware identity (Phid)', [validators.Optional()])
|
phid = StringField('Placeholder Hardware identity (Phid)', [validators.Optional()])
|
||||||
pallet = StringField('Identity of pallet', [validators.Optional()])
|
pallet = StringField('Identity of pallet', [validators.Optional()])
|
||||||
|
components = TextAreaField('Components', [validators.Optional()])
|
||||||
info = TextAreaField('Info', [validators.Optional()])
|
info = TextAreaField('Info', [validators.Optional()])
|
||||||
serial_number = StringField('Seria Number', [validators.Optional()])
|
serial_number = StringField('Seria Number', [validators.Optional()])
|
||||||
model = StringField('Model', [validators.Optional()])
|
model = StringField('Model', [validators.Optional()])
|
||||||
|
@ -392,6 +393,7 @@ class NewDeviceForm(FlaskForm):
|
||||||
self.phid.data = self._obj.placeholder.phid
|
self.phid.data = self._obj.placeholder.phid
|
||||||
self.pallet.data = self._obj.placeholder.pallet
|
self.pallet.data = self._obj.placeholder.pallet
|
||||||
self.info.data = self._obj.placeholder.info
|
self.info.data = self._obj.placeholder.info
|
||||||
|
self.components.data = self._obj.placeholder.components
|
||||||
self.serial_number.data = self._obj.serial_number
|
self.serial_number.data = self._obj.serial_number
|
||||||
self.model.data = self._obj.model
|
self.model.data = self._obj.model
|
||||||
self.manufacturer.data = self._obj.manufacturer
|
self.manufacturer.data = self._obj.manufacturer
|
||||||
|
@ -414,6 +416,35 @@ class NewDeviceForm(FlaskForm):
|
||||||
self.resolution.data = self._obj.resolution_width
|
self.resolution.data = self._obj.resolution_width
|
||||||
self.screen.data = self._obj.size
|
self.screen.data = self._obj.size
|
||||||
|
|
||||||
|
if self._obj.placeholder.is_abstract:
|
||||||
|
self.type.render_kw = disabled
|
||||||
|
self.amount.render_kw = disabled
|
||||||
|
self.id_device_supplier.render_kw = disabled
|
||||||
|
self.pallet.render_kw = disabled
|
||||||
|
self.info.render_kw = disabled
|
||||||
|
self.components.render_kw = disabled
|
||||||
|
self.serial_number.render_kw = disabled
|
||||||
|
self.model.render_kw = disabled
|
||||||
|
self.manufacturer.render_kw = disabled
|
||||||
|
self.appearance.render_kw = disabled
|
||||||
|
self.functionality.render_kw = disabled
|
||||||
|
self.brand.render_kw = disabled
|
||||||
|
self.generation.render_kw = disabled
|
||||||
|
self.version.render_kw = disabled
|
||||||
|
self.weight.render_kw = disabled
|
||||||
|
self.width.render_kw = disabled
|
||||||
|
self.height.render_kw = disabled
|
||||||
|
self.depth.render_kw = disabled
|
||||||
|
self.variant.render_kw = disabled
|
||||||
|
self.sku.render_kw = disabled
|
||||||
|
self.image.render_kw = disabled
|
||||||
|
if self._obj.type in ['Smartphone', 'Tablet', 'Cellphone']:
|
||||||
|
self.imei.render_kw = disabled
|
||||||
|
self.meid.render_kw = disabled
|
||||||
|
if self._obj.type == 'ComputerMonitor':
|
||||||
|
self.resolution.render_kw = disabled
|
||||||
|
self.screen.render_kw = disabled
|
||||||
|
|
||||||
def validate(self, extra_validators=None): # noqa: C901
|
def validate(self, extra_validators=None): # noqa: C901
|
||||||
error = ["Not a correct value"]
|
error = ["Not a correct value"]
|
||||||
is_valid = super().validate(extra_validators)
|
is_valid = super().validate(extra_validators)
|
||||||
|
@ -567,6 +598,7 @@ class NewDeviceForm(FlaskForm):
|
||||||
'phid': self.phid.data or None,
|
'phid': self.phid.data or None,
|
||||||
'id_device_supplier': self.id_device_supplier.data,
|
'id_device_supplier': self.id_device_supplier.data,
|
||||||
'info': self.info.data,
|
'info': self.info.data,
|
||||||
|
'components': self.components.data,
|
||||||
'pallet': self.pallet.data,
|
'pallet': self.pallet.data,
|
||||||
'is_abstract': False,
|
'is_abstract': False,
|
||||||
}
|
}
|
||||||
|
@ -575,10 +607,13 @@ class NewDeviceForm(FlaskForm):
|
||||||
|
|
||||||
def edit_device(self):
|
def edit_device(self):
|
||||||
self._obj.placeholder.phid = self.phid.data or self._obj.placeholder.phid
|
self._obj.placeholder.phid = self.phid.data or self._obj.placeholder.phid
|
||||||
self._obj.placeholder.id_device_supplier = self.id_device_supplier.data or None
|
if not self._obj.placeholder.is_abstract:
|
||||||
|
self._obj.placeholder.id_device_supplier = (
|
||||||
|
self.id_device_supplier.data or None
|
||||||
|
)
|
||||||
self._obj.placeholder.info = self.info.data or None
|
self._obj.placeholder.info = self.info.data or None
|
||||||
|
self._obj.placeholder.components = self.components.data or None
|
||||||
self._obj.placeholder.pallet = self.pallet.data or None
|
self._obj.placeholder.pallet = self.pallet.data or None
|
||||||
self._obj.placeholder.is_abstract = False
|
|
||||||
self._obj.model = self.model.data
|
self._obj.model = self.model.data
|
||||||
self._obj.manufacturer = self.manufacturer.data
|
self._obj.manufacturer = self.manufacturer.data
|
||||||
self._obj.serial_number = self.serial_number.data
|
self._obj.serial_number = self.serial_number.data
|
||||||
|
@ -601,7 +636,10 @@ class NewDeviceForm(FlaskForm):
|
||||||
self._obj.imei = self.imei.data
|
self._obj.imei = self.imei.data
|
||||||
self._obj.meid = self.meid.data
|
self._obj.meid = self.meid.data
|
||||||
|
|
||||||
if self.appearance.data and self.appearance.data != self._obj.appearance().name:
|
if (
|
||||||
|
self.appearance.data
|
||||||
|
and self.appearance.data != self._obj.appearance().name
|
||||||
|
):
|
||||||
self._obj.set_appearance(self.appearance.data)
|
self._obj.set_appearance(self.appearance.data)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -609,6 +647,7 @@ class NewDeviceForm(FlaskForm):
|
||||||
and self.functionality.data != self._obj.functionality().name
|
and self.functionality.data != self._obj.functionality().name
|
||||||
):
|
):
|
||||||
self._obj.set_functionality(self.functionality.data)
|
self._obj.set_functionality(self.functionality.data)
|
||||||
|
|
||||||
placeholder_log = PlaceholdersLog(
|
placeholder_log = PlaceholdersLog(
|
||||||
type="Update", source='Web form', placeholder=self._obj.placeholder
|
type="Update", source='Web form', placeholder=self._obj.placeholder
|
||||||
)
|
)
|
||||||
|
@ -1519,6 +1558,7 @@ class UploadPlaceholderForm(FlaskForm):
|
||||||
self.path_snapshots = {}
|
self.path_snapshots = {}
|
||||||
for i in data['Phid'].keys():
|
for i in data['Phid'].keys():
|
||||||
placeholder = None
|
placeholder = None
|
||||||
|
data['Phid'][i] = str(data['Phid'][i])
|
||||||
if data['Phid'][i]:
|
if data['Phid'][i]:
|
||||||
placeholder = Placeholder.query.filter_by(phid=data['Phid'][i]).first()
|
placeholder = Placeholder.query.filter_by(phid=data['Phid'][i]).first()
|
||||||
|
|
||||||
|
@ -1627,14 +1667,14 @@ class BindingForm(FlaskForm):
|
||||||
self.phid.errors = [txt]
|
self.phid.errors = [txt]
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self.device.placeholder:
|
if self.device.is_abstract() != 'Abstract':
|
||||||
txt = "This is not a device Workbench."
|
txt = "This is not a abstract device."
|
||||||
self.phid.errors = [txt]
|
self.phid.errors = [txt]
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not self.placeholder:
|
if not self.placeholder:
|
||||||
self.placeholder = Placeholder.query.filter(
|
self.placeholder = Placeholder.query.filter(
|
||||||
Placeholder.phid == self.phid.data, Placeholder.owner == g.user
|
Placeholder.phid == self.phid.data.strip(), Placeholder.owner == g.user
|
||||||
).first()
|
).first()
|
||||||
|
|
||||||
if not self.placeholder:
|
if not self.placeholder:
|
||||||
|
|
|
@ -37,7 +37,7 @@ from ereuse_devicehub.inventory.forms import (
|
||||||
)
|
)
|
||||||
from ereuse_devicehub.labels.forms import PrintLabelsForm
|
from ereuse_devicehub.labels.forms import PrintLabelsForm
|
||||||
from ereuse_devicehub.parser.models import PlaceholdersLog, SnapshotsLog
|
from ereuse_devicehub.parser.models import PlaceholdersLog, SnapshotsLog
|
||||||
from ereuse_devicehub.resources.action.models import Trade
|
from ereuse_devicehub.resources.action.models import ActionDevice, Trade
|
||||||
from ereuse_devicehub.resources.device.models import (
|
from ereuse_devicehub.resources.device.models import (
|
||||||
Computer,
|
Computer,
|
||||||
DataStorage,
|
DataStorage,
|
||||||
|
@ -191,15 +191,34 @@ class BindingView(GenericMixin):
|
||||||
.one()
|
.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
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
old_placeholder = device.binding
|
old_placeholder = device.binding
|
||||||
old_device_placeholder = old_placeholder.device
|
old_device_placeholder = old_placeholder.device
|
||||||
|
|
||||||
if old_placeholder.is_abstract:
|
if old_placeholder.is_abstract:
|
||||||
for plog in PlaceholdersLog.query.filter_by(
|
for plog in PlaceholdersLog.query.filter_by(
|
||||||
placeholder_id=old_placeholder.id
|
placeholder_id=old_placeholder.id
|
||||||
):
|
):
|
||||||
db.session.delete(plog)
|
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)
|
||||||
|
|
||||||
db.session.delete(old_device_placeholder)
|
db.session.delete(old_device_placeholder)
|
||||||
|
for tag in list(old_device_placeholder.tags):
|
||||||
|
tag.device = placeholder.device
|
||||||
|
|
||||||
device.binding = placeholder
|
device.binding = placeholder
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
@ -209,11 +228,16 @@ class BindingView(GenericMixin):
|
||||||
)
|
)
|
||||||
return flask.redirect(next_url)
|
return flask.redirect(next_url)
|
||||||
|
|
||||||
|
# import pdb; pdb.set_trace()
|
||||||
self.context.update(
|
self.context.update(
|
||||||
{
|
{
|
||||||
'device': device.binding.device,
|
'device': device.binding.device,
|
||||||
'placeholder': placeholder,
|
'placeholder': placeholder,
|
||||||
'page_title': 'Binding confirm',
|
'page_title': 'Binding confirm',
|
||||||
|
'actions': list(device.binding.device.actions)
|
||||||
|
+ list(placeholder.device.actions),
|
||||||
|
'tags': list(device.binding.device.tags)
|
||||||
|
+ list(placeholder.device.tags),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -242,10 +266,8 @@ class UnBindingView(GenericMixin):
|
||||||
self.get_context()
|
self.get_context()
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
self.clone_device(device)
|
new_device = self.clone_device(device)
|
||||||
next_url = url_for(
|
next_url = url_for('inventory.device_details', id=new_device.devicehub_id)
|
||||||
'inventory.device_details', id=placeholder.device.devicehub_id
|
|
||||||
)
|
|
||||||
messages.success('Device "{}" unbind successfully!'.format(phid))
|
messages.success('Device "{}" unbind successfully!'.format(phid))
|
||||||
return flask.redirect(next_url)
|
return flask.redirect(next_url)
|
||||||
|
|
||||||
|
@ -678,7 +700,13 @@ class ExportsView(View):
|
||||||
def devices_list(self):
|
def devices_list(self):
|
||||||
"""Get device query and put information in csv format."""
|
"""Get device query and put information in csv format."""
|
||||||
data = StringIO()
|
data = StringIO()
|
||||||
cw = csv.writer(data, delimiter=';', lineterminator="\n", quotechar='"', quoting=csv.QUOTE_ALL)
|
cw = csv.writer(
|
||||||
|
data,
|
||||||
|
delimiter=';',
|
||||||
|
lineterminator="\n",
|
||||||
|
quotechar='"',
|
||||||
|
quoting=csv.QUOTE_ALL,
|
||||||
|
)
|
||||||
first = True
|
first = True
|
||||||
|
|
||||||
for device in self.find_devices():
|
for device in self.find_devices():
|
||||||
|
@ -693,7 +721,13 @@ class ExportsView(View):
|
||||||
def metrics(self):
|
def metrics(self):
|
||||||
"""Get device query and put information in csv format."""
|
"""Get device query and put information in csv format."""
|
||||||
data = StringIO()
|
data = StringIO()
|
||||||
cw = csv.writer(data, delimiter=';', lineterminator="\n", quotechar='"', quoting=csv.QUOTE_ALL)
|
cw = csv.writer(
|
||||||
|
data,
|
||||||
|
delimiter=';',
|
||||||
|
lineterminator="\n",
|
||||||
|
quotechar='"',
|
||||||
|
quoting=csv.QUOTE_ALL,
|
||||||
|
)
|
||||||
first = True
|
first = True
|
||||||
devs_id = []
|
devs_id = []
|
||||||
# Get the allocate info
|
# Get the allocate info
|
||||||
|
@ -757,7 +791,13 @@ class ExportsView(View):
|
||||||
|
|
||||||
def lots_export(self):
|
def lots_export(self):
|
||||||
data = StringIO()
|
data = StringIO()
|
||||||
cw = csv.writer(data, delimiter=';', lineterminator="\n", quotechar='"', quoting=csv.QUOTE_ALL)
|
cw = csv.writer(
|
||||||
|
data,
|
||||||
|
delimiter=';',
|
||||||
|
lineterminator="\n",
|
||||||
|
quotechar='"',
|
||||||
|
quoting=csv.QUOTE_ALL,
|
||||||
|
)
|
||||||
|
|
||||||
cw.writerow(
|
cw.writerow(
|
||||||
[
|
[
|
||||||
|
@ -827,7 +867,13 @@ class ExportsView(View):
|
||||||
|
|
||||||
def devices_lots_export(self):
|
def devices_lots_export(self):
|
||||||
data = StringIO()
|
data = StringIO()
|
||||||
cw = csv.writer(data, delimiter=';', lineterminator="\n", quotechar='"', quoting=csv.QUOTE_ALL)
|
cw = csv.writer(
|
||||||
|
data,
|
||||||
|
delimiter=';',
|
||||||
|
lineterminator="\n",
|
||||||
|
quotechar='"',
|
||||||
|
quoting=csv.QUOTE_ALL,
|
||||||
|
)
|
||||||
head = [
|
head = [
|
||||||
'DHID',
|
'DHID',
|
||||||
'Lot Id',
|
'Lot Id',
|
||||||
|
|
|
@ -5,6 +5,7 @@ Revises: 2b90b41a556a
|
||||||
Create Date: 2022-07-27 14:40:15.513820
|
Create Date: 2022-07-27 14:40:15.513820
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
import citext
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
from alembic import context, op
|
from alembic import context, op
|
||||||
from sqlalchemy.dialects import postgresql
|
from sqlalchemy.dialects import postgresql
|
||||||
|
@ -41,6 +42,11 @@ def upgrade():
|
||||||
sa.Column('is_abstract', sa.Boolean(), nullable=True),
|
sa.Column('is_abstract', sa.Boolean(), nullable=True),
|
||||||
schema=f'{get_inv()}',
|
schema=f'{get_inv()}',
|
||||||
)
|
)
|
||||||
|
op.add_column(
|
||||||
|
'placeholder',
|
||||||
|
sa.Column('components', citext.CIText(), nullable=True),
|
||||||
|
schema=f'{get_inv()}',
|
||||||
|
)
|
||||||
op.add_column(
|
op.add_column(
|
||||||
'placeholder',
|
'placeholder',
|
||||||
sa.Column('owner_id', postgresql.UUID(), nullable=True),
|
sa.Column('owner_id', postgresql.UUID(), nullable=True),
|
||||||
|
@ -69,3 +75,4 @@ def downgrade():
|
||||||
)
|
)
|
||||||
op.drop_column('placeholder', 'owner_id', schema=f'{get_inv()}')
|
op.drop_column('placeholder', 'owner_id', schema=f'{get_inv()}')
|
||||||
op.drop_column('placeholder', 'is_abstract', schema=f'{get_inv()}')
|
op.drop_column('placeholder', 'is_abstract', schema=f'{get_inv()}')
|
||||||
|
op.drop_column('placeholder', 'components', schema=f'{get_inv()}')
|
||||||
|
|
|
@ -2,6 +2,7 @@ from citext import CIText
|
||||||
from flask import g
|
from flask import g
|
||||||
from sqlalchemy import BigInteger, Column, Sequence, SmallInteger
|
from sqlalchemy import BigInteger, Column, Sequence, SmallInteger
|
||||||
from sqlalchemy.dialects.postgresql import UUID
|
from sqlalchemy.dialects.postgresql import UUID
|
||||||
|
from sqlalchemy.orm import backref
|
||||||
|
|
||||||
from ereuse_devicehub.db import db
|
from ereuse_devicehub.db import db
|
||||||
from ereuse_devicehub.resources.action.models import Snapshot
|
from ereuse_devicehub.resources.action.models import Snapshot
|
||||||
|
@ -41,6 +42,8 @@ class SnapshotsLog(Thing):
|
||||||
|
|
||||||
def get_device(self):
|
def get_device(self):
|
||||||
if self.snapshot:
|
if self.snapshot:
|
||||||
|
if self.snapshot.device.binding:
|
||||||
|
return self.snapshot.device.binding.device.devicehub_id
|
||||||
return self.snapshot.device.devicehub_id
|
return self.snapshot.device.devicehub_id
|
||||||
|
|
||||||
return ''
|
return ''
|
||||||
|
@ -56,7 +59,11 @@ class PlaceholdersLog(Thing):
|
||||||
|
|
||||||
placeholder_id = Column(BigInteger, db.ForeignKey(Placeholder.id), nullable=True)
|
placeholder_id = Column(BigInteger, db.ForeignKey(Placeholder.id), nullable=True)
|
||||||
placeholder = db.relationship(
|
placeholder = db.relationship(
|
||||||
Placeholder, primaryjoin=placeholder_id == Placeholder.id
|
Placeholder,
|
||||||
|
backref=backref(
|
||||||
|
'placeholder_logs', lazy=True, cascade="all, delete-orphan", uselist=True
|
||||||
|
),
|
||||||
|
primaryjoin=placeholder_id == Placeholder.id,
|
||||||
)
|
)
|
||||||
owner_id = db.Column(
|
owner_id = db.Column(
|
||||||
UUID(as_uuid=True),
|
UUID(as_uuid=True),
|
||||||
|
|
|
@ -666,6 +666,20 @@ class Device(Thing):
|
||||||
action = next(e for e in reversed(actions) if e.type == 'VisualTest')
|
action = next(e for e in reversed(actions) if e.type == 'VisualTest')
|
||||||
action.functionality_range = value
|
action.functionality_range = value
|
||||||
|
|
||||||
|
def is_abstract(self):
|
||||||
|
if self.placeholder:
|
||||||
|
if self.placeholder.is_abstract:
|
||||||
|
return 'Abstract'
|
||||||
|
if self.placeholder.binding:
|
||||||
|
return 'Twin'
|
||||||
|
return 'Real'
|
||||||
|
if self.binding:
|
||||||
|
if self.binding.is_abstract:
|
||||||
|
return 'Abstract'
|
||||||
|
return 'Twin'
|
||||||
|
|
||||||
|
return ''
|
||||||
|
|
||||||
def is_status(self, action):
|
def is_status(self, action):
|
||||||
from ereuse_devicehub.resources.device import states
|
from ereuse_devicehub.resources.device import states
|
||||||
|
|
||||||
|
@ -869,6 +883,7 @@ class Placeholder(Thing):
|
||||||
phid = Column(Unicode(), nullable=False, default=create_phid)
|
phid = Column(Unicode(), nullable=False, default=create_phid)
|
||||||
pallet.comment = "used for identification where from where is this placeholders"
|
pallet.comment = "used for identification where from where is this placeholders"
|
||||||
info = db.Column(CIText())
|
info = db.Column(CIText())
|
||||||
|
components = Column(CIText())
|
||||||
info.comment = "more info of placeholders"
|
info.comment = "more info of placeholders"
|
||||||
is_abstract = db.Column(Boolean, default=False)
|
is_abstract = db.Column(Boolean, default=False)
|
||||||
id_device_supplier = db.Column(CIText())
|
id_device_supplier = db.Column(CIText())
|
||||||
|
@ -883,7 +898,9 @@ class Placeholder(Thing):
|
||||||
)
|
)
|
||||||
device = db.relationship(
|
device = db.relationship(
|
||||||
Device,
|
Device,
|
||||||
backref=backref('placeholder', lazy=True, cascade="all, delete-orphan", uselist=False),
|
backref=backref(
|
||||||
|
'placeholder', lazy=True, cascade="all, delete-orphan", uselist=False
|
||||||
|
),
|
||||||
primaryjoin=device_id == Device.id,
|
primaryjoin=device_id == Device.id,
|
||||||
)
|
)
|
||||||
device_id.comment = "datas of the placeholder"
|
device_id.comment = "datas of the placeholder"
|
||||||
|
|
|
@ -139,7 +139,7 @@
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
{% if placeholder.device.actions or device.actions %}
|
{% if actions %}
|
||||||
<h2>Actions</h2>
|
<h2>Actions</h2>
|
||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
|
@ -151,15 +151,37 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="table-success text-right">
|
<td class="table-success text-right">
|
||||||
{% for a in placeholder.device.actions %}
|
{% for a in actions %}
|
||||||
* {{ a.t }}<br />
|
* {{ a.t }}<br />
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</td>
|
</td>
|
||||||
<td class="table-danger">
|
<td class="table-danger">
|
||||||
{% for a in device.actions %}
|
</td>
|
||||||
* {{ a.t }}<br />
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
{% if tags %}
|
||||||
|
<h2>Tags</h2>
|
||||||
|
<table class="table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr class="text-center">
|
||||||
|
<th scope="col">Info to be Entered</th>
|
||||||
|
<th scope="col">Info to be Decoupled</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="table-success text-right">
|
||||||
|
{% for tag in tags %}
|
||||||
|
* {{ tag.id }}<br />
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</td>
|
</td>
|
||||||
|
<td class="table-danger">
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -142,6 +142,19 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group mb-2">
|
||||||
|
<label for="label" class="form-label">{{ form.components.label }}</label>
|
||||||
|
{{ form.components(class_="form-control") }}
|
||||||
|
<small class="text-muted form-text">Description of components</small>
|
||||||
|
{% if form.components.errors %}
|
||||||
|
<p class="text-danger">
|
||||||
|
{% for error in form.components.errors %}
|
||||||
|
{{ error }}<br/>
|
||||||
|
{% endfor %}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="from-group has-validation mb-2" id="Serial_number">
|
<div class="from-group has-validation mb-2" id="Serial_number">
|
||||||
<label for="serialNumber" class="form-label">{{ form.serial_number.label }}</label>
|
<label for="serialNumber" class="form-label">{{ form.serial_number.label }}</label>
|
||||||
{{ form.serial_number(class_="form-control") }}
|
{{ form.serial_number(class_="form-control") }}
|
||||||
|
|
|
@ -62,13 +62,13 @@
|
||||||
<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.binding %}
|
{% if device.is_abstract() == 'Abstract' %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#binding">Binding</button>
|
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#binding">Binding</button>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if device.placeholder and placeholder.binding %}
|
{% if device.is_abstract() == 'Twin' %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{{ url_for('inventory.unbinding', phid=placeholder.phid) }}">Unbinding</a>
|
<a class="nav-link" href="{{ url_for('inventory.unbinding', phid=placeholder.phid) }}">Unbinding</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -79,7 +79,21 @@
|
||||||
|
|
||||||
<div class="tab-pane fade {% if active_binding %}profile-overview{% else %}show active{% endif %}" id="type">
|
<div class="tab-pane fade {% if active_binding %}profile-overview{% else %}show active{% endif %}" id="type">
|
||||||
<h5 class="card-title">Details</h5>
|
<h5 class="card-title">Details</h5>
|
||||||
{% if device.placeholder %}(<a href="{{ url_for('inventory.device_edit', id=device.devicehub_id)}}">edit</a>){% endif %}
|
{% if device.placeholder %}
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-lg-3 col-md-4 label ">
|
||||||
|
(<a href="{{ url_for('inventory.device_edit', id=device.devicehub_id)}}">Edit Device</a>)
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-9 col-md-8">{{ device.is_abstract() }}</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if device.placeholder %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-3 col-md-4 label ">Phid</div>
|
||||||
|
<div class="col-lg-9 col-md-8">{{ device.placeholder.phid }}</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>
|
||||||
|
@ -88,17 +102,17 @@
|
||||||
|
|
||||||
<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 }}</div>
|
<div class="col-lg-9 col-md-8">{{ 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 }}</div>
|
<div class="col-lg-9 col-md-8">{{ 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 }}</div>
|
<div class="col-lg-9 col-md-8">{{ device.serial_number or ''}}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -208,6 +222,7 @@
|
||||||
|
|
||||||
<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 Details</h5>
|
||||||
|
{% if device.binding %}
|
||||||
<div class="list-group col-6">
|
<div class="list-group col-6">
|
||||||
{% for component in device.components|sort(attribute='type') %}
|
{% for component in device.components|sort(attribute='type') %}
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
|
@ -227,8 +242,13 @@
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="col-6">
|
||||||
|
{{ device.placeholder.components or '' }}
|
||||||
</div>
|
</div>
|
||||||
{% if placeholder.binding %}
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% if device.is_abstract() %}
|
||||||
<div class="tab-pane fade {% if active_binding %}show active{% else %}profile-overview{% endif %}" id="binding">
|
<div class="tab-pane fade {% if active_binding %}show active{% else %}profile-overview{% endif %}" id="binding">
|
||||||
<h5 class="card-title">Binding</h5>
|
<h5 class="card-title">Binding</h5>
|
||||||
<div class="list-group col-6">
|
<div class="list-group col-6">
|
||||||
|
@ -238,7 +258,7 @@
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="list-group col-6">
|
<div class="list-group col-6">
|
||||||
<form action="{{ url_for('inventory.device_details', id=placeholder.binding.devicehub_id) }}" method="post">
|
<form action="{{ url_for('inventory.device_details', id=device.devicehub_id) }}" method="post">
|
||||||
{{ form_binding.csrf_token }}
|
{{ form_binding.csrf_token }}
|
||||||
{% for field in form_binding %}
|
{% for field in form_binding %}
|
||||||
{% if field != form_binding.csrf_token %}
|
{% if field != form_binding.csrf_token %}
|
||||||
|
|
|
@ -402,7 +402,7 @@
|
||||||
<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">PHID</th>
|
||||||
<th scope="col">Is Abstract</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>
|
||||||
|
@ -448,7 +448,7 @@
|
||||||
{{ dev.binding and dev.binding.phid or dev.placeholder and dev.placeholder.phid or '' }}
|
{{ dev.binding and dev.binding.phid or dev.placeholder and dev.placeholder.phid or '' }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ dev.binding and dev.binding.is_abstract and '✓' or dev.placeholder and dev.placeholder.is_abstract and '✓' or '' }}
|
{{ dev.is_abstract() }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{% for t in dev.tags | sort(attribute="id") %}
|
{% for t in dev.tags | sort(attribute="id") %}
|
||||||
|
|
Reference in New Issue