{% extends 'base.html' %} {% load i18n %} {% block content %} <div class="position-fixed" style="bottom: 2rem; right: 2rem; z-index: 9999; display: flex; gap: 0.5rem;"> <button class="btn btn-warning d-flex align-items-center shadow" type="button" data-bs-toggle="offcanvas" data-bs-target="#notesOffcanvas" aria-controls="notesOffcanvas" data-bs-toggle="tooltip" data-bs-placement="left" title="{% trans 'View recent notes' %}"> <i class="bi bi-journal-text me-1"></i> {% trans "Journal" %} </button> </div> <!-- side panel for latest notes --> <div class="offcanvas offcanvas-end" tabindex="-1" id="notesOffcanvas" aria-labelledby="notesOffcanvasLabel"> <div class="offcanvas-header"> <h5 id="notesOffcanvasLabel">{% trans "Latest Notes" %}</h5> <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button> </div> <div class="offcanvas-body" style="margin-bottom: 5rem;"> {% for note in device_notes|slice:":4" %} <div class="card mb-3 shadow-sm"> <div class="card-body"> <div> <small class="text-muted"> {{ note.date|timesince }} {% trans "ago" %} </small> {% if user == note.user or user.is_admin %} <span class="badge bg-warning text-dark ms-2">{% trans "Editable" %}</span> </div> <blockquote class="blockquote mt-2 p-2 bg-light fst-italic" contenteditable="true" style="font-size: 1.2em!important" data-note-id="{{ note.id }}" title="{% trans 'Click to edit this note' %}" oninput="toggleSaveLink(this)"> {% else %} </div> <blockquote style="font-size: 1.2em!important" class="blockquote mt-2 p-2 fst-italic"> {% endif %} <p data-note-id="{{ note.id }}"> {{ note.description }} </p> <footer class="blockquote-footer text-end mt-2" contenteditable="false"> <small>{{ note.user.get_full_name|default:note.user.username }}</small> </footer> </blockquote> {% if user == note.user or user.is_admin %} <div class="d-flex justify-content-end align-items-center"> <!-- update note button --> <form id="updateNoteForm{{ note.id }}" method="post" action="{% url 'action:update_note' note.id %}" class="d-inline" > {% csrf_token %} <input type="hidden" name="description" id="descriptionInput{{ note.id }}" value=""> <a type="submit" id="saveLink{{ note.id }}" class="text-muted disabled me-4 border border-light rounded" style="pointer-events: none;" title="{% trans 'Save changes' %}" onclick="submitUpdatedNote('{{ note.id }}'); return false;" > <i class="fas fa-save px-1"></i> </a> </form> <!-- delete note button --> <button type="button" class="btn btn-link btn-outline-danger btn-sm text-danger" id="deleteIcon{{ note.id }}" title="{% trans 'Delete note' %}" data-bs-toggle="collapse" data-bs-target="#confirmDelete{{ note.id }}"> <i class="bi bi-trash"></i> </button> </div> <form class="d-inline" method="post" action="{% url 'action:delete_note' note.id %}"> {% csrf_token %} <div class="collapse mt-2" id="confirmDelete{{ note.id }}"> <div class="card card-body border border-danger text-center"> <p class="mb-2">{% trans 'Are you sure you want to delete this note?' %}</p> <a href="#" class="btn btn-sm btn-outline-danger" onclick="submitDeleteForm({{ note.id }}); return false;" > {% trans 'Confirm delete' %} </a> </div> </div> </form> {% endif %} </div> </div> {% empty %} <p>{% trans "No notes available." %}</p> {% endfor %} </div> </div> <!-- Top bar buttons --> <div class="row"> <div class="col"> <h3>{{ object.shortid }}</h3> </div> <div class="col text-end"> <div class="btn-group" role="group" aria-label="Actions"> <!-- change state button --> {% if state_definitions %} <div class="dropdown ms-2"> <a class="btn btn-green-admin dropdown-toggle" id="addStateDropdown" data-bs-toggle="dropdown" aria-expanded="false"> {% trans "Change state" %} {% if device_states %} ({{ device_states.0.state }}) {% else %} ( {% trans "None" %} ) {% endif %} </a> <ul class="dropdown-menu" aria-labelledby="addStateDropdown" style="width: 100%;"> {% for state in state_definitions %} <li style="width: 100%;"> <form id="changeStateForm{{ state.id }}" method="post" action="{% url 'action:change_state' %}"> {% csrf_token %} <input type="hidden" name="previous_state" value="{{ device_states.0.state|default:"nil" }}"> <input type="hidden" name="snapshot_uuid" value="{{ object.last_uuid }}"> <input type="hidden" name="new_state" value="{{ state.state }}"> <a class="dropdown-item d-flex justify-content-between align-items-center" href="#" onclick="document.getElementById('changeStateForm{{ state.id }}').submit(); return false;"> <span class="font-monospace">{{ state.state }}</span> <span class="badge bg-secondary rounded-pill-sm">{{ forloop.counter }}</span> </a> </form> </li> {% endfor %} </ul> </div> {% else %} <button class="btn btn-green-admin" type="button" disabled> <i class="bi bi-plus"></i> {% trans "Change state" %} {% if device_states %} ({{ device_states.0.state }}) {% endif %} </button> {% endif %} <!-- Add note button --> <button class="btn btn-warning ms-2" type="button" data-bs-toggle="modal" data-bs-target="#addNoteModal"> <i class="bi bi-sticky"></i> {% trans "Add a note" %} </button> </div> </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="#log" class="nav-link" data-bs-toggle="tab" data-bs-target="#log">{% trans 'Log' %}</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"> {% include 'tabs/general_details.html' %} {% include 'tabs/log.html' %} {% include 'tabs/user_properties.html' %} {% include 'tabs/documents.html' %} {% include 'tabs/lots.html' %} {% include 'tabs/components.html' %} {% include 'tabs/evidences.html' %} <!-- Add a note popup --> <div class="modal fade" id="addNoteModal" tabindex="-1" aria-labelledby="addNoteModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="addNoteModalLabel">{% trans "Add a Note" %}</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{% trans 'Close' %}"></button> </div> <div class="modal-body"> <form method="post" action="{% url 'action:add_note' %}"> {% csrf_token %} <div class="mb-3"> <input type="hidden" name="snapshot_uuid" value="{{ object.last_uuid }}"> <label for="noteDescription" class="form-label">{% trans "Note" %}</label> <textarea class="form-control" id="noteDescription" name="note" placeholder="Max 250 characters" name="note" rows="3" required></textarea> </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-green-admin">{% trans "Save Note" %}</button> </div> </form> </div> </div> </div> </div> {% 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() } } }) //Enable save button on note if changes are made to it function toggleSaveLink(blockquoteElem) { const saveLink = document.getElementById("saveLink" + blockquoteElem.dataset.noteId); saveLink.classList.remove("disabled", "text-muted", "border-light"); saveLink.classList.add("text-success", "border-success"); saveLink.style.pointerEvents = "auto"; } //updates note-update-form with new value from blockquote function submitUpdatedNote(noteId) { const noteParagraph = document.querySelector('p[data-note-id="' + noteId + '"]'); const newText = noteParagraph.innerText.trim(); const descriptionField = document.getElementById('descriptionInput' + noteId); descriptionField.value = newText; document.getElementById('updateNoteForm' + noteId).submit(); } //simpler are u sure? confirmation message function submitDeleteForm(noteId) { document.getElementById('confirmDelete' + noteId).closest('form').submit(); } </script> {% endblock %}