view dpp page

This commit is contained in:
Cayo Puigdefabregas 2024-11-20 18:06:52 +01:00
parent e6c1ede93c
commit 1c58bff515
5 changed files with 654 additions and 193 deletions

View file

@ -25,6 +25,7 @@ class Device:
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
# the id is the chid of the device # the id is the chid of the device
self.id = kwargs["id"] self.id = kwargs["id"]
self.uuid = kwargs.get("uuid")
self.pk = self.id self.pk = self.id
self.shortid = self.pk[:6].upper() self.shortid = self.pk[:6].upper()
self.algorithm = None self.algorithm = None
@ -103,6 +104,14 @@ class Device:
self.evidences = [Evidence(u) for u in self.uuids] self.evidences = [Evidence(u) for u in self.uuids]
def get_last_evidence(self): def get_last_evidence(self):
if self.last_evidence:
return
if self.uuid:
import pdb; pdb.set_trace()
self.last_evidence = Evidence(self.uuid)
return
annotations = self.get_annotations() annotations = self.get_annotations()
if not annotations.count(): if not annotations.count():
return return
@ -126,6 +135,8 @@ class Device:
return False return False
def last_uuid(self): def last_uuid(self):
if self.uuid:
return self.uuid
return self.uuids[0] return self.uuids[0]
def get_lots(self): def get_lots(self):
@ -263,41 +274,35 @@ class Device:
@property @property
def is_websnapshot(self): def is_websnapshot(self):
if not self.last_evidence: self.get_last_evidence()
self.get_last_evidence()
return self.last_evidence.doc['type'] == "WebSnapshot" return self.last_evidence.doc['type'] == "WebSnapshot"
@property @property
def last_user_evidence(self): def last_user_evidence(self):
if not self.last_evidence: self.get_last_evidence()
self.get_last_evidence()
return self.last_evidence.doc['kv'].items() return self.last_evidence.doc['kv'].items()
@property @property
def manufacturer(self): def manufacturer(self):
if not self.last_evidence: self.get_last_evidence()
self.get_last_evidence()
return self.last_evidence.get_manufacturer() return self.last_evidence.get_manufacturer()
@property @property
def serial_number(self): def serial_number(self):
if not self.last_evidence: self.get_last_evidence()
self.get_last_evidence()
return self.last_evidence.get_serial_number() return self.last_evidence.get_serial_number()
@property @property
def type(self): def type(self):
self.get_last_evidence()
if self.last_evidence.doc['type'] == "WebSnapshot": if self.last_evidence.doc['type'] == "WebSnapshot":
return self.last_evidence.doc.get("device", {}).get("type", "") return self.last_evidence.doc.get("device", {}).get("type", "")
if not self.last_evidence:
self.get_last_evidence()
return self.last_evidence.get_chassis() return self.last_evidence.get_chassis()
@property @property
def model(self): def model(self):
if not self.last_evidence: self.get_last_evidence()
self.get_last_evidence()
return self.last_evidence.get_model() return self.last_evidence.get_model()
@property @property
@ -308,6 +313,5 @@ class Device:
@property @property
def components(self): def components(self):
if not self.last_evidence: self.get_last_evidence()
self.get_last_evidence()
return self.last_evidence.get_components() return self.last_evidence.get_components()

View file

@ -1,4 +1,3 @@
import json
from django.http import JsonResponse from django.http import JsonResponse
from django.http import Http404 from django.http import Http404
@ -15,6 +14,7 @@ from dashboard.mixins import DashboardView, Http403
from evidence.models import Annotation from evidence.models import Annotation
from lot.models import LotTag from lot.models import LotTag
from dpp.models import Proof from dpp.models import Proof
from dpp.api_dlt import PROOF_TYPE
from device.models import Device from device.models import Device
from device.forms import DeviceFormSet from device.forms import DeviceFormSet
@ -104,7 +104,10 @@ class DetailsView(DashboardView, TemplateView):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
self.object.initial() self.object.initial()
lot_tags = LotTag.objects.filter(owner=self.request.user.institution) lot_tags = LotTag.objects.filter(owner=self.request.user.institution)
dpps = Proof.objects.filter(uuid__in=self.object.uuids) dpps = Proof.objects.filter(
uuid__in=self.object.uuids,
type=PROOF_TYPE["IssueDPP"]
)
context.update({ context.update({
'object': self.object, 'object': self.object,
'snapshot': self.object.get_last_evidence(), 'snapshot': self.object.get_last_evidence(),

View file

@ -0,0 +1,497 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{ object.type }}</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/css/bootstrap.min.css" rel="stylesheet" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css" />
<style>
body {
font-size: 0.875rem;
background-color: #f8f9fa;
display: flex;
flex-direction: column;
min-height: 100vh;
}
.custom-container {
background-color: #ffffff;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
padding: 30px;
margin-top: 30px;
flex-grow: 1;
}
.section-title {
color: #7a9f4f;
border-bottom: 2px solid #9cc666;
padding-bottom: 10px;
margin-bottom: 20px;
font-size: 1.5em;
}
.info-row {
margin-bottom: 10px;
}
.info-label {
font-weight: bold;
color: #545f71;
}
.info-value {
color: #333;
}
.component-card {
background-color: #f8f9fa;
border-left: 4px solid #9cc666;
margin-bottom: 15px;
transition: all 0.3s ease;
}
.component-card:hover {
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
transform: translateY(-2px);
}
.hash-value {
word-break: break-all;
background-color: #f3f3f3;
padding: 5px;
border-radius: 4px;
font-family: monospace;
font-size: 0.9em;
border: 1px solid #e0e0e0;
}
.card-title {
color: #9cc666;
}
.btn-primary {
background-color: #9cc666;
border-color: #9cc666;
padding: 0.1em 2em;
font-weight: 700;
}
.btn-primary:hover {
background-color: #8ab555;
border-color: #8ab555;
}
.btn-green-user {
background-color: #c7e3a3;
}
.btn-grey {
background-color: #f3f3f3;
}
footer {
background-color: #545f71;
color: #ffffff;
text-align: center;
padding: 10px 0;
margin-top: 20px;
}
</style>
</head>
<body>
<div class="container custom-container">
<nav class="header-nav ms-auto">
<div class="d-flex align-items-right">
<span class="nav-item">
{% if not roles and user.is_anonymous %}
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#validateModal">Validate</button>
{% else %}
<button class="btn btn-primary" id="buttonRole" data-bs-toggle="modal" data-bs-target="#rolesModal">Select your role</button>
<a class="btn btn-primary" href="{% url 'login:logout' %}?next={{ path }}">Logout</a>
{% endif %}
</span>
</div>
{% if role %}
<div class="d-flex justify-content-end">
<span class="nav-item">
Current Role: {{ role }}
</span>
</div>
{% endif %}
</nav>
<h1 class="text-center mb-4" style="color: #545f71;">{{ object.manufacturer }} {{ object.type }} {{ object.model }}</h1>
<div class="row">
<div class="col-lg-6">
{% if manuals.details.logo %}
<img style="max-width: 50px; margin-right: 15px;" src="{{ manuals.details.logo }}" />
{% endif %}
</div>
<div class="col-lg-6">
{% if manuals.details.image %}
<img style="width: 100px;" src="{{ manuals.details.image }}" />
{% endif %}
</div>
</div>
<div class="row">
<div class="col-lg-6">
<h2 class="section-title">Details</h2>
<div class="info-row row">
<div class="col-md-4 info-label">Phid</div>
<div class="col-md-8 info-value">
<div class="hash-value">{{ object.id }}</div>
</div>
</div>
<div class="info-row row">
<div class="col-md-4 info-label">Type</div>
<div class="col-md-8 info-value">{{ object.type }}</div>
</div>
{% if object.is_websnapshot %}
{% for snapshot_key, snapshot_value in object.last_user_evidence %}
<div class="info-row row">
<div class="col-md-4 info-label">{{ snapshot_key }}</div>
<div class="col-md-8 info-value">{{ snapshot_value|default:'' }}</div>
</div>
{% endfor %}
{% else %}
<div class="info-row row">
<div class="col-md-4 info-label">Manufacturer</div>
<div class="col-md-8 info-value">{{ object.manufacturer|default:'' }}</div>
</div>
<div class="info-row row">
<div class="col-md-4 info-label">Model</div>
<div class="col-md-8 info-value">{{ object.model|default:'' }}</div>
</div>
{% if user.is_authenticated %}
<div class="info-row row">
<div class="col-md-4 info-label">Serial Number</div>
<div class="col-md-8 info-value">{{ object.serial_number|default:'' }}</div>
</div>
{% endif %}
{% endif %}
</div>
<div class="col-lg-6">
<h2 class="section-title">Identifiers</h2>
{% for chid in object.hids %}
<div class="info-row">
<div class="hash-value">{{ chid|default:'' }}</div>
</div>
{% endfor %}
</div>
</div>
<h2 class="section-title mt-5">Components</h2>
<div class="row">
{% for component in object.components %}
<div class="col-md-6 mb-3">
<div class="card component-card">
<div class="card-body">
<h5 class="card-title">{{ component.type }}</h5>
<p class="card-text">
{% for component_key, component_value in component.items %}
{% if component_key not in 'actions,type' %}
{% if component_key != 'serialNumber' or user.is_authenticated %}
<strong>{{ component_key }}:</strong> {{ component_value }}<br />
{% endif %}
{% endif %}
{% endfor %}
</p>
</div>
</div>
</div>
{% endfor %}
</div>
{% if manuals.icecat %}
<h5 class="card-title">Icecat data sheet</h5>
<div class="row">
<div class="col-12 list-group-item d-flex align-items-center">
{% if manuals.details.logo %}
<img style="max-width: 50px; margin-right: 15px;" src="{{ manuals.details.logo }}" />
{% endif %}
{% if manuals.details.image %}
<img style="max-width: 100px; margin-right: 15px;" src="{{ manuals.details.image }}" />
{% endif %}
{% if manuals.details.pdf %}
<a href="{{ manuals.details.pdf }}" target="_blank">{{ manuals.details.title }}</a><br />
{% else %}
{{ manuals.details.title }}<br />
{% endif %}
</div>
<div class="col-12 accordion-item">
<h5 class="card-title accordion-header">
<button class="accordion-button collapsed" data-bs-target="#manuals-icecat" type="button"
data-bs-toggle="collapse" aria-expanded="false">
More examples
</button>
</h5>
<div id="manuals-icecat" class="row accordion-collapse collapse">
<div class="accordion-body">
{% for m in manuals.icecat %}
<div class="list-group-item d-flex align-items-center">
{% if m.logo %}
<img style="max-width: 50px; margin-right: 15px;" src="{{ m.logo }}" />
{% endif %}
{% if m.pdf %}
<a href="{{ m.pdf }}" target="_blank">{{ m.title }}</a><br />
{% else %}
{{ m.title }}<br />
{% endif %}
</div>
{% endfor %}
</div>
</div>
</div>
</div>
{% endif %}
{% if manuals.laer %}
<div class="row mt-3">
<div class="col-12">
<h5 class="card-title">Recycled Content</h5>
<div class="row mb-3">
<div class="col-sm-2">
Metal
</div>
<div class="col-sm-10">
<div class="progress">
<div class="progress-bar"
role="progressbar"
style="width: {{ manuals.laer.0.metal }}%"
aria-valuenow="{{ manuals.laer.0.metal }}"
aria-valuemin="0"
aria-valuemax="100">{{ manuals.laer.0.metal }}%
</div>
</div>
</div>
</div>
<div class="row mb-3">
<div class="col-sm-2">
Plastic post Consumer
</div>
<div class="col-sm-10">
<div class="progress">
<div class="progress-bar"
role="progressbar"
style="width: {{ manuals.laer.0.plastic_post_consumer }}%"
aria-valuenow="{{ manuals.laer.0.plastic_post_consumer }}"
aria-valuemin="0"
aria-valuemax="100">{{ manuals.laer.0.plastic_post_consumer }}%
</div>
</div>
</div>
</div>
<div class="row mb-3">
<div class="col-sm-2">
Plastic post Industry
</div>
<div class="col-sm-10">
<div class="progress">
<div class="progress-bar"
role="progressbar"
style="width: {{ manuals.laer.0.plastic_post_industry }}%"
aria-valuenow="{{ manuals.laer.0.plastic_post_industry }}"
aria-valuemin="0"
aria-valuemax="100">{{ manuals.laer.0.plastic_post_industry }}%
</div>
</div>
</div>
</div>
</div>
</div>
{% endif %}
{% if manuals.energystar %}
<div class="row mt-3">
<div class="col-12">
<h5 class="card-title">Energy spent</h5>
{% if manuals.energystar.long_idle_watts %}
<div class="row mb-3">
<div class="col-sm-10">
Consumption when inactivity power function is activated (watts)
</div>
<div class="col-sm-2">
{{ manuals.energystar.long_idle_watts }}
</div>
</div>
{% endif %}
{% if manuals.energystar.short_idle_watts %}
<div class="row mb-3">
<div class="col-sm-10">
Consumption when inactivity power function is not activated (watts)
</div>
<div class="col-sm-2">
{{ manuals.energystar.short_idle_watts }}
</div>
</div>
{% endif %}
{% if manuals.energystar.sleep_mode_watts %}
<div class="row mb-3">
<div class="col-sm-10">
sleep_mode_watts
Consumption when computer goes into sleep mode (watts)
</div>
<div class="col-sm-2">
{{ manuals.energystar.sleep_mode_watts }}
</div>
</div>
{% endif %}
{% if manuals.energystar.off_mode_watts %}
<div class="row mb-3">
<div class="col-sm-10">
Consumption when the computer is off (watts)
</div>
<div class="col-sm-2">
{{ manuals.energystar.off_mode_watts }}
</div>
</div>
{% endif %}
{% if manuals.energystar.tec_allowance_kwh %}
<div class="row mb-3">
<div class="col-sm-10">
Power allocation for normal operation (kwh)
</div>
<div class="col-sm-2">
{{ manuals.energystar.tec_allowance_kwh }}
</div>
</div>
{% endif %}
{% if manuals.energystar.tec_of_model_kwh %}
<div class="row mb-3">
<div class="col-sm-10">
Consumption of the model configuration (kwh)
</div>
<div class="col-sm-2">
{{ manuals.energystar.tec_of_model_kwh }}
</div>
</div>
{% endif %}
{% if manuals.energystar.tec_requirement_kwh %}
<div class="row mb-3">
<div class="col-sm-10">
Energy allowance provided (kwh)
</div>
<div class="col-sm-2">
{{ manuals.energystar.tec_requirement_kwh }}
</div>
</div>
{% endif %}
{% if manuals.energystar.work_off_mode_watts %}
<div class="row mb-3">
<div class="col-sm-10">
The lowest power mode which cannot be switched off (watts)
</div>
<div class="col-sm-2">
{{ manuals.energystar.work_off_mode_watts }}
</div>
</div>
{% endif %}
{% if manuals.energystar.work_weighted_power_of_model_watts %}
<div class="row mb-3">
<div class="col-sm-10">
Weighted energy consumption from all its states (watts)
</div>
<div class="col-sm-2">
{{ manuals.energystar.work_weighted_power_of_model_watts }}
</div>
</div>
{% endif %}
</div>
</div>
{% endif %}
{% if manuals.ifixit %}
<div class="row">
<div class="col-12 accordion-item">
<h5 class="card-title accordion-header">
<button class="accordion-button collapsed" data-bs-target="#manuals-repair" type="button"
data-bs-toggle="collapse" aria-expanded="false">
Repair manuals
</button>
</h5>
<div id="manuals-repair" class="row accordion-collapse collapse">
<div class="list-group col">
{% for m in manuals.ifixit %}
<div class="list-group-item d-flex align-items-center">
{% if m.image %}
<img style="max-width: 100px; margin-right: 15px;" src="{{ m.image }}" />
{% endif %}
{% if m.url %}
<a href="{{ m.url }}" target="_blank">{{ m.title }}</a><br />
{% else %}
{{ m.title }}<br />
{% endif %}
</div>
{% endfor %}
</div>
</div>
</div>
</div>
{% endif %}
<footer>
<p>
&copy;{% now 'Y' %}eReuse. All rights reserved.
</p>
</footer>
{% if user.is_anonymous and not roles %}
<div class="modal fade" id="validateModal" tabindex="-1" style="display: none;" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Validate as <span id="title-action"></span></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<a class="btn btn-primary" type="button"
href="{% url 'login:login' %}?next={{ path }}">
User of system
</a>
{% if oidc %}
<br />
<a class="btn btn-primary mt-3" type="button" href="{# url 'oidc:login_other_inventory' #}?next={{ path }}">
User of other inventory
</a>
{% endif %}
</div>
<div class="modal-footer"></div>
</div>
</div>
</div>
{% else %}
<div class="modal fade" id="rolesModal" tabindex="-1" style="display: none;" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<form action="{{ path }}" method="get">
<div class="modal-header">
<h5 class="modal-title">Select your Role <span id="title-action"></span></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<select name="role">
{% for k, v in roles %}
<option value="{{ k }}" {% if v == role %}selected=selected{% endif %}>{{ v }}</option>
{% endfor %}
</select>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<input type="submit" class="btn btn-primary" value="Send" />
</div>
</form>
</div>
</div>
</div>
{% endif %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View file

@ -1,171 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{ object.type }}</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/css/bootstrap.min.css" rel="stylesheet" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css" />
<style>
body {
font-size: 0.875rem;
background-color: #f8f9fa;
display: flex;
flex-direction: column;
min-height: 100vh;
}
.custom-container {
background-color: #ffffff;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
padding: 30px;
margin-top: 30px;
flex-grow: 1;
}
.section-title {
color: #7a9f4f;
border-bottom: 2px solid #9cc666;
padding-bottom: 10px;
margin-bottom: 20px;
font-size: 1.5em;
}
.info-row {
margin-bottom: 10px;
}
.info-label {
font-weight: bold;
color: #545f71;
}
.info-value {
color: #333;
}
.component-card {
background-color: #f8f9fa;
border-left: 4px solid #9cc666;
margin-bottom: 15px;
transition: all 0.3s ease;
}
.component-card:hover {
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
transform: translateY(-2px);
}
.hash-value {
word-break: break-all;
background-color: #f3f3f3;
padding: 5px;
border-radius: 4px;
font-family: monospace;
font-size: 0.9em;
border: 1px solid #e0e0e0;
}
.card-title {
color: #9cc666;
}
.btn-primary {
background-color: #9cc666;
border-color: #9cc666;
padding: 0.1em 2em;
font-weight: 700;
}
.btn-primary:hover {
background-color: #8ab555;
border-color: #8ab555;
}
.btn-green-user {
background-color: #c7e3a3;
}
.btn-grey {
background-color: #f3f3f3;
}
footer {
background-color: #545f71;
color: #ffffff;
text-align: center;
padding: 10px 0;
margin-top: 20px;
}
</style>
</head>
<body>
<div class="container custom-container">
<h1 class="text-center mb-4" style="color: #545f71;">{{ object.manufacturer }} {{ object.type }} {{ object.model }}</h1>
<div class="row">
<div class="col-lg-6">
<h2 class="section-title">Details</h2>
<div class="info-row row">
<div class="col-md-4 info-label">Phid</div>
<div class="col-md-8 info-value">
<div class="hash-value">{{ object.id }}</div>
</div>
</div>
<div class="info-row row">
<div class="col-md-4 info-label">Type</div>
<div class="col-md-8 info-value">{{ object.type }}</div>
</div>
{% if object.is_websnapshot %}
{% for snapshot_key, snapshot_value in object.last_user_evidence %}
<div class="info-row row">
<div class="col-md-4 info-label">{{ snapshot_key }}</div>
<div class="col-md-8 info-value">{{ snapshot_value|default:'' }}</div>
</div>
{% endfor %}
{% else %}
<div class="info-row row">
<div class="col-md-4 info-label">Manufacturer</div>
<div class="col-md-8 info-value">{{ object.manufacturer|default:'' }}</div>
</div>
<div class="info-row row">
<div class="col-md-4 info-label">Model</div>
<div class="col-md-8 info-value">{{ object.model|default:'' }}</div>
</div>
{% if user.is_authenticated %}
<div class="info-row row">
<div class="col-md-4 info-label">Serial Number</div>
<div class="col-md-8 info-value">{{ object.serial_number|default:'' }}</div>
</div>
{% endif %}
{% endif %}
</div>
<div class="col-lg-6">
<h2 class="section-title">Identifiers</h2>
{% for chid in object.hids %}
<div class="info-row">
<div class="hash-value">{{ chid|default:'' }}</div>
</div>
{% endfor %}
</div>
</div>
<h2 class="section-title mt-5">Components</h2>
<div class="row">
{% for component in object.components %}
<div class="col-md-6 mb-3">
<div class="card component-card">
<div class="card-body">
<h5 class="card-title">{{ component.type }}</h5>
<p class="card-text">
{% for component_key, component_value in component.items %}
{% if component_key not in 'actions,type' %}
{% if component_key != 'serialNumber' or user.is_authenticated %}
<strong>{{ component_key }}:</strong> {{ component_value }}<br />
{% endif %}
{% endif %}
{% endfor %}
</p>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<footer>
<p>
&copy;{% now 'Y' %}eReuse. All rights reserved.
</p>
</footer>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View file

@ -1,14 +1,26 @@
import json
import logging
from django.http import JsonResponse, Http404 from django.http import JsonResponse, Http404
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView
from device.models import Device from device.models import Device
from dpp.models import Proof
logger = logging.getLogger('django')
class PublicDeviceWebView(TemplateView): class PublicDeviceWebView(TemplateView):
template_name = "device_web.html" template_name = "device_did.html"
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
self.pk = kwargs['pk'] self.pk = kwargs['pk']
self.object = Device(id=self.pk) chid = self.pk.split(":")[0]
proof = Proof.objects.filter(signature=self.pk).first()
if proof:
self.object = Device(id=chid, uuid=proof.uuid)
else:
self.object = Device(id=chid)
if not self.object.last_evidence: if not self.object.last_evidence:
raise Http404 raise Http404
@ -18,12 +30,24 @@ class PublicDeviceWebView(TemplateView):
return super().get(request, *args, **kwargs) return super().get(request, *args, **kwargs)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) self.context = super().get_context_data(**kwargs)
self.object.initial() self.object.initial()
context.update({ roles = [("Operator", "Operator")]
'object': self.object role = "Operator"
if self.request.user.is_anonymous:
roles = []
role = None
self.context.update({
'object': self.object,
'role': role,
'roles': roles,
'path': self.request.path,
'last_dpp': "",
'before_dpp': "",
}) })
return context if not self.request.user.is_anonymous:
self.get_manuals()
return self.context
@property @property
def public_fields(self): def public_fields(self):
@ -58,3 +82,107 @@ class PublicDeviceWebView(TemplateView):
device_data = self.get_device_data() device_data = self.get_device_data()
return JsonResponse(device_data) return JsonResponse(device_data)
def get_manuals(self):
manuals = {
'ifixit': [],
'icecat': [],
'details': {},
'laer': [],
'energystar': {},
}
try:
params = {
"manufacturer": self.object.manufacturer,
"model": self.object.model,
}
self.params = json.dumps(params)
manuals['ifixit'] = self.request_manuals('ifixit')
manuals['icecat'] = self.request_manuals('icecat')
manuals['laer'] = self.request_manuals('laer')
manuals['energystar'] = self.request_manuals('energystar') or {}
if manuals['icecat']:
manuals['details'] = manuals['icecat'][0]
except Exception as err:
logger.error("Error: {}".format(err))
self.context['manuals'] = manuals
self.parse_energystar()
def parse_energystar(self):
if not self.context.get('manuals', {}).get('energystar'):
return
# Defined in:
# https://dev.socrata.com/foundry/data.energystar.gov/j7nq-iepp
energy_types = [
'functional_adder_allowances_kwh',
'tec_allowance_kwh',
'long_idle_watts',
'short_idle_watts',
'off_mode_watts',
'sleep_mode_watts',
'tec_of_model_kwh',
'tec_requirement_kwh',
'work_off_mode_watts',
'work_weighted_power_of_model_watts',
]
energy = {}
for field in energy_types:
energy[field] = []
for e in self.context['manuals']['energystar']:
for field in energy_types:
for k, v in e.items():
if not v:
continue
if field in k:
energy[field].append(v)
for k, v in energy.items():
if not v:
energy[k] = 0
continue
tt = sum([float(i) for i in v])
energy[k] = round(tt / len(v), 2)
self.context['manuals']['energystar'] = energy
def request_manuals(self, prefix):
#TODO reimplement manuals service
response = {
"laer": [{"metal": 40, "plastic_post_consumer": 27, "plastic_post_industry": 34}],
"energystar": [{
'functional_adder_allowances_kwh': 180,
"long_idle_watts": 240,
"short_idle_watts": 120,
"sleep_mode_watts": 30,
"off_mode_watts": 3,
"tec_allowance_kwh": 180,
"tec_of_model_kwh": 150,
"tec_requirement_kwh": 220,
"work_off_mode_watts": 70,
"work_weighted_power_of_model_watts": 240
}],
"ifixit": [
{
"image": "https://guide-images.cdn.ifixit.com/igi/156EpI4YdQeVfVPa.medium",
"url": "https://es.ifixit.com/Gu%C3%ADa/HP+ProBook+450+G4+Back+Panel+Replacement/171196?lang=en",
"title": "HP ProBook 450 G4 Back Panel Replacement"
},
{
"image": "https://guide-images.cdn.ifixit.com/igi/usTIqCKpuxVWC3Ix.140x105",
"url": "https://es.ifixit.com/Gu%C3%ADa/HP+ProBook+450+G4+Display+Assembly+Replacement/171101?lang=en",
"title": "Display Assembly Replacement"
}
],
"icecat": [
{
"logo": "https://images.icecat.biz/img/brand/thumb/1_cf8603f6de7b4c4d8ac4f5f0ef439a05.jpg",
"image": "https://guide-images.cdn.ifixit.com/igi/Q2nYjTIQfG6GaI5B.standard",
"pdf": "https://icecat.biz/rest/product-pdf?productId=32951710&lang=en",
"title": "HP ProBook 450 G3"
}
]
}
return response.get(prefix, {})