471 lines
17 KiB
HTML
471 lines
17 KiB
HTML
{% extends 'base.html' %}
|
|
{% load i18n %}
|
|
|
|
{% block content %}
|
|
|
|
<div class="row">
|
|
<div class="col">
|
|
<h3>{{ object.shortid }}</h3>
|
|
</div>
|
|
<div class="col text-end">
|
|
{% if state_definitions %}
|
|
<div class="dropdown">
|
|
<button class="btn btn-green-admin dropdown-toggle" type="button" id="addStateDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
|
{% trans "Action" %}
|
|
</button>
|
|
<ul class="dropdown-menu" aria-labelledby="addStateDropdown">
|
|
{% for state in state_definitions %}
|
|
<li>
|
|
<a class="dropdown-item" href="#" data-bs-toggle="modal" data-bs-target="#addStateModal{{ state.id }}">
|
|
{{ state.state }}
|
|
</a>
|
|
</li>
|
|
{% endfor %}
|
|
</ul>
|
|
</div>
|
|
{% else %}
|
|
<button class="btn btn-green-admin" type="button" disabled>
|
|
{% trans "Action" %}
|
|
</button>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col">
|
|
<ul class="nav nav-tabs nav-tabs-bordered">
|
|
<li class="nav-item">
|
|
<a href="#details" class="nav-link active" data-bs-toggle="tab" data-bs-target="#details">{% trans 'General details' %}</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="#states" class="nav-link" data-bs-toggle="tab" data-bs-target="#states">{% trans 'States' %}</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="#user_properties" class="nav-link" data-bs-toggle="tab" data-bs-target="#user_properties">{% trans 'User properties' %}</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="#documents" class="nav-link" data-bs-toggle="tab" data-bs-target="#documents">{% trans 'Documents' %}</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="#lots" class="nav-link" data-bs-toggle="tab" data-bs-target="#lots">{% trans 'Lots' %}</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="#components" class="nav-link" data-bs-toggle="tab" data-bs-target="#components">{% trans 'Components' %}</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="#evidences" class="nav-link" data-bs-toggle="tab" data-bs-target="#evidences">{% trans 'Evidences' %}</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a class="nav-link" href="{% url 'device:device_web' object.id %}" target="_blank">Web</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="tab-content pt-4">
|
|
<!-- Device Details -->
|
|
<div class="tab-pane fade show active" id="details">
|
|
<div class="row">
|
|
|
|
<div class="col-lg-6">
|
|
<h5 class="card-title">{% trans 'Details' %}</h5>
|
|
<hr>
|
|
<div class="row mb-3">
|
|
<div class="col-sm-4 text-muted fw-bold">{% trans 'Phid' %}</div>
|
|
<div class="col-sm-8">{{ object.id }}</div>
|
|
</div>
|
|
|
|
{% if object.is_eraseserver %}
|
|
<div class="row mb-3">
|
|
<div class="col-sm-4 text-muted fw-bold">{% trans 'Is an erase server' %}</div>
|
|
<div class="col-sm-8">{% trans 'Yes' %}</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="row mb-3">
|
|
<div class="col-sm-4 text-muted fw-bold">{% trans 'Type' %}</div>
|
|
<div class="col-sm-8">{{ object.type }}</div>
|
|
</div>
|
|
|
|
{% if object.is_websnapshot and object.last_user_evidence %}
|
|
{% for k, v in object.last_user_evidence.items %}
|
|
<div class="row mb-3">
|
|
<div class="col-sm-4 text-muted fw-bold">{{ k }}</div>
|
|
<div class="col-sm-8">{{ v|default:'' }}</div>
|
|
</div>
|
|
{% endfor %}
|
|
{% else %}
|
|
<div class="row mb-3">
|
|
<div class="col-sm-4 text-muted fw-bold">{% trans 'Manufacturer' %}</div>
|
|
<div class="col-sm-8">{{ object.manufacturer|default:'' }}</div>
|
|
</div>
|
|
|
|
<div class="row mb-3">
|
|
<div class="col-sm-4 text-muted fw-bold">{% trans 'Model' %}</div>
|
|
<div class="col-sm-8">{{ object.model|default:'' }}</div>
|
|
</div>
|
|
|
|
<div class="row mb-3">
|
|
<div class="col-sm-4 text-muted fw-bold">{% trans 'Serial Number' %}</div>
|
|
<div class="col-sm-8">{{ object.serial_number|default:'' }}</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="row mb-3">
|
|
<div class="col-sm-4 text-muted fw-bold">{% trans 'Identifiers' %}</div>
|
|
<div class="col-sm-8">
|
|
{% for chid in object.hids %}
|
|
<div>{{ chid|default:'' }}</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<!-- Device Current State -->
|
|
<div class="col-lg-6">
|
|
<h5 class="card-title">{% trans 'Current State' %}</h5>
|
|
<hr>
|
|
<div class="table-responsive">
|
|
<table class="table table-striped table-bordered">
|
|
<thead class="table">
|
|
<tr>
|
|
<th scope="col">{% trans 'State' %}</th>
|
|
<th scope="col">{% trans 'User' %}</th>
|
|
<th scope="col">{% trans 'Date' %}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% if device_states %}
|
|
<tr class="table-success">
|
|
<td>{{ device_states.0.state }}</td>
|
|
<td>{{ device_states.0.user.responsable_person|default:device_states.0.user.username }}</td>
|
|
<td>{{ device_states.0.date|date:"SHORT_DATETIME_FORMAT" }}</td>
|
|
</tr>
|
|
{% else %}
|
|
<tr>
|
|
<td colspan="3" class="text-center">{% trans 'No state recorded.' %}</td>
|
|
</tr>
|
|
{% endif %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- TODO: display last note? -->
|
|
{% if last_note %}
|
|
<div class="row mb-3">
|
|
<div class="col-sm-4 text-muted fw-bold">{% trans 'Note' %}</div>
|
|
<div class="col-sm-8">{{ object.last_state.note }}</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<!-- States list -->
|
|
|
|
<div class="tab-pane fade" id="states">
|
|
<h5 class="card-title mb-3">{% trans 'History of States' %}</h5>
|
|
<div class="table-responsive">
|
|
<table class="table table-striped table-bordered">
|
|
<thead class="table">
|
|
<tr>
|
|
<th scope="col">{% trans 'Date' %}</th>
|
|
<th scope="col">{% trans 'User' %}</th>
|
|
<th scope="col">{% trans 'State' %}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for state_change in device_states %}
|
|
<tr {% if forloop.first %}class="table-success"{% endif %}>
|
|
<td><strong>{{ state_change.state }}</strong></td>
|
|
|
|
<td>{{ state_change.user.responsable_person|default:state_change.user.username }}</td>
|
|
<td>{{ state_change.date|date:"SHORT_DATETIME_FORMAT" }}</td>
|
|
</tr>
|
|
{% empty %}
|
|
<tr>
|
|
<td colspan="3" class="text-center">{% trans 'No state changes recorded.' %}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-pane fade" id="user_properties">
|
|
<div class="btn-group mt-1 mb-3">
|
|
<a href="{% url 'device:add_user_property' object.pk %}" class="btn btn-primary">
|
|
<i class="bi bi-plus"></i>
|
|
{% trans 'New user property' %}
|
|
</a>
|
|
</div>
|
|
|
|
<h5 class="card-title">{% trans 'User properties' %}</h5>
|
|
<table class="table table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th scope="col">
|
|
{% trans 'Key' %}
|
|
</th>
|
|
<th scope="col">
|
|
{% trans 'Value' %}
|
|
</th>
|
|
<th scope="col" data-type="date" data-format="YYYY-MM-DD HH:mm">
|
|
{% trans 'Created on' %}
|
|
</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for a in object.get_user_properties %}
|
|
<tr>
|
|
<td>{{ a.key }}</td>
|
|
<td>{{ a.value }}</td>
|
|
<td>{{ a.created }}</td>
|
|
<td>
|
|
<div class="btn-group float-end">
|
|
<button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#editModal{{ a.id }}">
|
|
<i class="bi bi-pencil"></i> {% trans 'Edit' %}
|
|
</button>
|
|
<button type="button" class="btn btn-sm btn-danger" data-bs-toggle="modal" data-bs-target="#deleteModal{{ a.id }}">
|
|
<i class="bi bi-trash"></i>
|
|
</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- pop up modal for delete confirmation -->
|
|
{% for a in object.get_user_properties %}
|
|
<div class="modal fade" id="deleteModal{{ a.id }}" tabindex="-1" aria-labelledby="deleteModalLabel{{ a.id }}" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="deleteModalLabel{{ a.id }}">{% trans "Confirm Deletion" %}</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p><strong>{% trans "Key:" %}</strong> {{ a.key }}</p>
|
|
<p><strong>{% trans "Value:" %}</strong> {{ a.value }}</p>
|
|
<p><strong>{% trans "Created on:" %}</strong> {{ a.created }}</p>
|
|
</div>
|
|
<div class="modal-footer justify-content-center">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{% trans "Cancel" %}</button>
|
|
<form method="post" action="{% url 'device:delete_user_property' a.id %}">
|
|
{% csrf_token %}
|
|
<button type="submit" class="btn btn-danger">{% trans "Delete" %}</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
|
|
<!-- popup modals for edit button -->
|
|
{% for a in object.get_user_properties %}
|
|
<div class="modal fade" id="editModal{{ a.id }}" tabindex="-1" aria-labelledby="editModalLabel{{ a.id }}" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="editModalLabel{{ a.id }}">{% trans "Edit User Property" %}</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form id="editForm{{ a.id }}" method="post" action="{% url 'device:update_user_property' a.id %}">
|
|
{% csrf_token %}
|
|
<div class="mb-3">
|
|
<label for="key" class="form-label">{% trans "Key" %}</label>
|
|
<input type="text" class="form-control" id="key" name="key" value="{{ a.key }}">
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="value" class="form-label">{% trans "Value" %}</label>
|
|
<input type="text" class="form-control" id="value" name="value" value="{{ a.value }}">
|
|
</div>
|
|
<div class="modal-footer justify-content-center">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{% trans "Cancel" %}</button>
|
|
<button type="submit" class="btn btn-primary">{% trans "Save changes" %}</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
|
|
<div class="tab-pane fade" id="documents">
|
|
<div class="btn-group mt-1 mb-3">
|
|
<a href="{% url 'device:add_document' object.pk %}" class="btn btn-primary">
|
|
<i class="bi bi-plus"></i>
|
|
{% trans 'Add new document' %}
|
|
</a>
|
|
</div>
|
|
|
|
<h5 class="card-title">{% trans 'Documents' %}</h5>
|
|
<table class="table table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th scope="col">
|
|
{% trans 'Key' %}
|
|
</th>
|
|
<th scope="col">
|
|
{% trans 'Value' %}
|
|
</th>
|
|
<th scope="col" data-type="date" data-format="YYYY-MM-DD HH:mm">
|
|
{% trans 'Created on' %}
|
|
</th>
|
|
<th></th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for a in object.get_user_documents %}
|
|
<tr>
|
|
<td>{{ a.key }}</td>
|
|
<td>{{ a.value }}</td>
|
|
<td>{{ a.created }}</td>
|
|
<td></td>
|
|
<td></td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="tab-pane fade" id="lots">
|
|
{% for tag in lot_tags %}
|
|
<h5 class="card-title">{{ tag }}</h5>
|
|
{% for lot in object.lots %}
|
|
{% if lot.type == tag %}
|
|
<div class="row mb-3">
|
|
<div class="col">
|
|
<a href="{% url 'dashboard:lot' lot.id %}">{{ lot.name }}</a>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
{% endfor %}
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<div class="tab-pane fade" id="components">
|
|
<h5 class="card-title">{% trans 'Components last evidence' %}</h5>
|
|
<div class="list-group col-6">
|
|
{% for c in object.components %}
|
|
<div class="list-group-item">
|
|
<div class="d-flex w-100 justify-content-between">
|
|
<h5 class="mb-1">{{ c.type }}</h5>
|
|
<small class="text-muted">{{ evidence.created }}</small>
|
|
</div>
|
|
<p class="mb-1">
|
|
{% for k, v in c.items %}
|
|
{% if k not in 'actions,type' %}
|
|
{{ k }}: {{ v }}<br />
|
|
{% endif %}
|
|
{% endfor %}
|
|
</p>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-pane fade" id="evidences">
|
|
<h5 class="card-title">{% trans 'List of evidences' %}</h5>
|
|
<div class="list-group col-6">
|
|
{% for snap in object.evidences %}
|
|
<div class="list-group-item">
|
|
<div class="d-flex w-100 justify-content-between">
|
|
<small class="text-muted">{{ snap.created }}</small>
|
|
</div>
|
|
<p class="mb-1">
|
|
<a href="{% url 'evidence:details' snap.uuid %}">{{ snap.uuid }}</a>
|
|
</p>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- add state to device - popup modal-->
|
|
{% if state_definitions %}
|
|
{% for state in state_definitions %}
|
|
<div class="modal fade" id="addStateModal{{ state.id }}" tabindex="-1" aria-labelledby="addStateModalLabel{{ state.id }}" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
|
|
<form method="post" action="{% url 'action:new_action'%}">
|
|
{% csrf_token %}
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="addStateModalLabel{{ state.id }}">{% trans "Summary of changes" %}</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body m-2">
|
|
|
|
|
|
<div class="mb-3">
|
|
<div class="d-flex align-items-center">
|
|
<i class="bi bi-arrow-right-circle text-danger me-2"></i>
|
|
|
|
<span class="text-danger fw-bold me-2">{% trans "From:" %}</span>
|
|
<span class="text-danger fw-italic">state_placeholder</span>
|
|
</div>
|
|
<div class="d-flex align-items-center mt-2">
|
|
<i class="bi bi-arrow-right-circle text-success me-2"></i>
|
|
<span class="text-success fw-bold me-2">{% trans "To:" %}</span>
|
|
<span class="text-success fw-italic">{{ state.state }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-check form-switch mt-3 d-flex justify-content-end">
|
|
<label class="form-check-label font-monospace" for="addNoteCheckbox{{ state.id }}">
|
|
{% trans "Add a note" %}
|
|
</label>
|
|
<input class="form-check-input ms-2" type="checkbox" id="addNoteCheckbox{{ state.id }}" data-bs-toggle="collapse" data-bs-target="#collapseInput{{ state.id }}" name="add_note">
|
|
</div>
|
|
|
|
<div class="mb-3 mt-2 collapse" id="collapseInput{{ state.id }}">
|
|
<textarea type="text" class="form-control" id="stateNote{{ state.id }}" name="note" rows="4" maxlength="200" placeholder="{% trans "Max 200 characters" %}"></textarea>
|
|
</div>
|
|
|
|
<input type="hidden" name="state_id" value="{{ state.id }}">
|
|
<input type="hidden" name="snapshot_uuid" value="{{ object.last_uuid }}">
|
|
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{% trans "Cancel" %}</button>
|
|
<button type="submit" class="btn btn-primary">{% trans "Add State" %}</button>
|
|
</div>
|
|
|
|
</div>
|
|
</form>
|
|
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
{% endif %}
|
|
|
|
{% endblock %}
|
|
|
|
{% block extrascript %}
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
// Obtener el hash de la URL (ejemplo: #components)
|
|
const hash = window.location.hash
|
|
|
|
// Verificar si hay un hash en la URL
|
|
if (hash) {
|
|
// Buscar el botón o enlace que corresponde al hash y activarlo
|
|
const tabTrigger = document.querySelector(`[data-bs-target="${hash}"]`)
|
|
|
|
if (tabTrigger) {
|
|
// Crear una instancia de tab de Bootstrap para activar el tab
|
|
const tab = new bootstrap.Tab(tabTrigger)
|
|
tab.show()
|
|
}
|
|
}
|
|
})
|
|
</script>
|
|
{% endblock %}
|