Merge pull request #426 from eReuse/feature/2078-public-page
add new version of public page
This commit is contained in:
commit
bea63148b2
|
@ -1,400 +1,181 @@
|
|||
{% import 'devices/macros.html' as macros %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<link href="https://stackpath.bootstrapcdn.com/bootswatch/3.3.7/flatly/bootstrap.min.css"
|
||||
rel="stylesheet"
|
||||
integrity="sha384-+ENW/yibaokMnme+vBLnHMphUYxHs34h9lpdbSLuAwGkOKFRl4C34WkjazBtb7eT"
|
||||
crossorigin="anonymous">
|
||||
<script src="https://use.fontawesome.com/7553aecc27.js"></script>
|
||||
<title>Devicehub | {{ device.__format__('t') }}</title>
|
||||
<style>
|
||||
/*Sticky footer*/
|
||||
html {
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
}
|
||||
{% extends "ereuse_devicehub/base.html" %}
|
||||
{% block page_title %}Device {{ device.dhid }}{% endblock %}
|
||||
|
||||
body {
|
||||
margin-bottom: 60px; /* Margin bottom by footer height */
|
||||
}
|
||||
{% block body %}
|
||||
<main>
|
||||
|
||||
.footer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 6em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<nav class="navbar navbar-default" style="background-color: gainsboro; margin: 0 !important">
|
||||
<div class="container-fluid">
|
||||
<a href="https://www.usody.com/" target="_blank">
|
||||
<h1 align="center">Usody Public Link</h1>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="container-fluid">
|
||||
<section class="container mt-3">
|
||||
<div class="row">
|
||||
<div class="page-header col-md-6 col-md-offset-3">
|
||||
<h1>{% if abstract %}Real device {% endif %}{{ device.__format__('t') or '' }}<br>
|
||||
<small>{{ device.__format__('s') or '' }}</small>
|
||||
</h1>
|
||||
|
||||
<div class="col">
|
||||
<div class="col-xl-12">
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h3 class="nav-link mt-5" style="color: #993365">{{ device_real.type }} - {{ device_real.verbose_name }}</h3>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h5 class="card-title">Basic</h5>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
Usody Identifier (DHID)
|
||||
</div>
|
||||
<div class="col">
|
||||
{{ device_real.dhid }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="col">
|
||||
Inventory Identifier (PHID)
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<ul>
|
||||
{% for key, value in device.public_properties.items() %}
|
||||
<li>{{ key }}: {{ value or '' }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% if isinstance(device, d.Computer) %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Range</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if device.processor_model %}
|
||||
<tr>
|
||||
<td>
|
||||
CPU – {{ device.processor_model }}
|
||||
</td>
|
||||
<td>
|
||||
Processor Rate = {% if device.rate %}
|
||||
{{ device.rate.processor_range }}
|
||||
({{ device.rate.processor }})
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if device.ram_size %}
|
||||
<tr>
|
||||
<td>
|
||||
RAM – {{ device.ram_size // 1000 }} GB
|
||||
{{ macros.component_type(device.components, 'RamModule') }}
|
||||
</td>
|
||||
<td>
|
||||
RAM Rate = {% if device.rate %}
|
||||
{{ device.rate.ram_range }}
|
||||
({{ device.rate.ram }})
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if device.data_storage_size %}
|
||||
<tr>
|
||||
<td>
|
||||
Data Storage – {{ device.data_storage_size // 1000 }} GB
|
||||
{{ macros.component_type(device.components, 'SolidStateDrive') }}
|
||||
{{ macros.component_type(device.components, 'HardDrive') }}
|
||||
</td>
|
||||
<td>
|
||||
Data Storage Rate = {% if device.rate %}
|
||||
{{ device.rate.data_storage_range }}
|
||||
({{ device.rate.data_storage }})
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if device.graphic_card_model %}
|
||||
<tr>
|
||||
<td>
|
||||
Graphics – {{ device.graphic_card_model }}
|
||||
{{ macros.component_type(device.components, 'GraphicCard') }}
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if device.network_speeds %}
|
||||
<tr>
|
||||
<td>
|
||||
Network –
|
||||
{% if device.network_speeds[0] %}
|
||||
Ethernet
|
||||
{% if device.network_speeds[0] != None %}
|
||||
max. {{ device.network_speeds[0] }} Mbps
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if device.network_speeds[0] and device.network_speeds[1] %}
|
||||
+
|
||||
{% endif %}
|
||||
{% if device.network_speeds[1] %}
|
||||
WiFi
|
||||
{% if device.network_speeds[1] != None %}
|
||||
max. {{ device.network_speeds[1] }} Mbps
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{{ macros.component_type(device.components, 'NetworkAdapter') }}
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="col">
|
||||
{{ device_real.phid() }}
|
||||
</div>
|
||||
<h4>Actual Status</h4>
|
||||
<ol>
|
||||
<li>
|
||||
<strong>
|
||||
Lifecycle Status
|
||||
</strong>
|
||||
—
|
||||
{% if device.status %}
|
||||
{{ device.status.type }}
|
||||
{% endif %}
|
||||
</li>
|
||||
<li>
|
||||
<strong>
|
||||
Allocate Status
|
||||
</strong>
|
||||
—
|
||||
{% if device.allocated_status %}
|
||||
{{ device.allocated_status.type }}
|
||||
{% endif %}
|
||||
</li>
|
||||
<li>
|
||||
<strong>
|
||||
Physical Status
|
||||
</strong>
|
||||
—
|
||||
{% if device.physical_status %}
|
||||
{{ device.physical_status.type }}
|
||||
{% endif %}
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<h4>Public traceability log of the device</h4>
|
||||
<div class="text-right">
|
||||
<small>Latest one.</small>
|
||||
</div>
|
||||
<ol>
|
||||
{% for action in device.public_actions %}
|
||||
<li>
|
||||
<strong>
|
||||
{{ device.is_status(action) }}
|
||||
{% if not device.is_status(action) %}
|
||||
{{ action.type }}
|
||||
{% endif %}
|
||||
</strong>
|
||||
—
|
||||
{% if device.is_status(action) %}
|
||||
{{ action }} {{ action.type }}
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
Type
|
||||
</div>
|
||||
<div class="col">
|
||||
{{ device_real.type or '- not detected -' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
Manufacturer
|
||||
</div>
|
||||
<div class="col">
|
||||
{{ device_real.manufacturer or '- not detected -' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
Model
|
||||
</div>
|
||||
<div class="col">
|
||||
{{ device_real.model or '- not detected -' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
Part Number
|
||||
</div>
|
||||
<div class="col">
|
||||
{{ device_real.part_number or '- not detected -' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
Serial Number
|
||||
</div>
|
||||
<div class="col">
|
||||
- anonymized -
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
</div>
|
||||
<div class="col-5">
|
||||
<h5 class="card-title">Status</h5>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="label"><b>Physical</b></div>
|
||||
<div>{{ device_real.physical_status and device.physical_status.type or '- not status -' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="label"><b>Lifecycle</b></div>
|
||||
<div>{{ device_real.status and device_real.status.type or '- not status -' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="label"><b>Allocation</b></div>
|
||||
<div>
|
||||
{% if device_real.allocated %}
|
||||
Allocated
|
||||
{% else %}
|
||||
{{ action }}
|
||||
Not allocated
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col-6">
|
||||
<h5 class="card-title">Components</h5>
|
||||
<div class="row">
|
||||
{% if placeholder.binding %}
|
||||
<div class="list-group col">
|
||||
{% for component in placeholder.binding.components|sort(attribute='type') %}
|
||||
<div class="list-group-item">
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<h5 class="mb-1">{{ component.type }}</h5>
|
||||
<small class="text-muted">{{ component.created.strftime('%H:%M %d-%m-%Y') }}</small>
|
||||
</div>
|
||||
<p class="mb-1">
|
||||
{{ component.manufacturer }}<br />
|
||||
{{ component.model }}<br />
|
||||
</p>
|
||||
<small class="text-muted">
|
||||
{% if component.type in ['RamModule', 'HardDrive', 'SolidStateDrive'] %}
|
||||
{{ component.size }}MB
|
||||
{% 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>
|
||||
{% 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 class="list-group col">
|
||||
<div class="list-group-item">
|
||||
- not detected -
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<footer class="container-fluid footer">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h5 class="card-title">Repair history</h5>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
Page generated by:<br>
|
||||
<img style="height: 9em"
|
||||
src="{{ url_for('Device.static', filename='usody-logo-v4.png') }}">
|
||||
<div class="list-group col">
|
||||
{% for action in placeholder.actions %}
|
||||
<div class="list-group-item d-flex justify-content-between align-items-center">
|
||||
{{ action.type }} {{ action.severity }}
|
||||
<small class="text-muted">{{ action.created.strftime('%H:%M %d-%m-%Y') }}</small>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
<!-- ======= Footer ======= -->
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<footer class="footer">
|
||||
<div class="copyright">
|
||||
© Copyright <strong><span>Usody</span></strong>. All Rights Reserved
|
||||
</div>
|
||||
<div class="credits">
|
||||
<a href="https://help.usody.com/en/" target="_blank">Help</a> |
|
||||
<a href="https://pangea.org/es/politica-de-privacidad/" target="_blank">Privacy</a> |
|
||||
<a href="https://pangea.org/aviso-legal/" target="_blank">Terms</a>
|
||||
</div>
|
||||
<div class="credits">
|
||||
DeviceHub
|
||||
</div>
|
||||
</footer><!-- End Footer -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock body%}
|
||||
|
|
|
@ -148,8 +148,17 @@ class DeviceView(View):
|
|||
if device.is_abstract() == 'Twin':
|
||||
abstract = device.placeholder.binding
|
||||
|
||||
placeholder = device.binding or device.placeholder
|
||||
device_abstract = placeholder and placeholder.binding or device
|
||||
device_real = placeholder and placeholder.device or device
|
||||
return render_template(
|
||||
'devices/layout.html', device=device, states=states, abstract=abstract
|
||||
'devices/layout.html',
|
||||
placeholder=placeholder,
|
||||
device=device,
|
||||
device_abstract=device_abstract,
|
||||
device_real=device_real,
|
||||
states=states,
|
||||
abstract=abstract,
|
||||
)
|
||||
|
||||
@auth.Auth.requires_auth
|
||||
|
|
|
@ -417,7 +417,6 @@ def test_get_device_permissions(
|
|||
|
||||
html, _ = client.get(res=d.Device, item=s['device']['devicehubID'], accept=ANY)
|
||||
assert 'intel atom cpu n270 @ 1.60ghz' in html
|
||||
assert '00:24:8C:7F:CF:2D – 100 Mbps' in html
|
||||
pc2, res2 = user2.get(res=d.Device, item=s['device']['devicehubID'], accept=ANY)
|
||||
assert res2.status_code == 200
|
||||
assert pc2 == html
|
||||
|
@ -549,7 +548,6 @@ def test_device_public(user: UserClient, client: Client):
|
|||
s, _ = user.post(file('asus-eee-1000h.snapshot.11'), res=m.Snapshot)
|
||||
html, _ = client.get(res=d.Device, item=s['device']['devicehubID'], accept=ANY)
|
||||
assert 'intel atom cpu n270 @ 1.60ghz' in html
|
||||
assert '00:24:8C:7F:CF:2D – 100 Mbps' in html
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
|
|
Reference in New Issue