add device details
This commit is contained in:
parent
07d0aa6f1c
commit
df63af3ee0
55
dashboard/mixins.py
Normal file
55
dashboard/mixins.py
Normal file
|
@ -0,0 +1,55 @@
|
|||
from django.urls import resolve
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.views.generic.base import TemplateView
|
||||
|
||||
|
||||
class Http403(PermissionDenied):
|
||||
status_code = 403
|
||||
default_detail = _('Permission denied. User is not authenticated')
|
||||
default_code = 'forbidden'
|
||||
|
||||
def __init__(self, details=None, code=None):
|
||||
if details is not None:
|
||||
self.detail = details or self.default_details
|
||||
if code is not None:
|
||||
self.code = code or self.default_code
|
||||
|
||||
|
||||
class DashboardView(LoginRequiredMixin):
|
||||
login_url = "/login/"
|
||||
template_name = "dashboard.html"
|
||||
breadcrumb = ""
|
||||
title = ""
|
||||
subtitle = ""
|
||||
section = ""
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'title': self.title,
|
||||
'subtitle': self.subtitle,
|
||||
'breadcrumb': self.breadcrumb,
|
||||
# 'icon': self.icon,
|
||||
'section': self.section,
|
||||
'path': resolve(self.request.path).url_name,
|
||||
'user': self.request.user,
|
||||
})
|
||||
return context
|
||||
|
||||
|
||||
class DetailsMixin(DashboardView, TemplateView):
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.pk = kwargs['pk']
|
||||
self.object = get_object_or_404(self.model, pk=self.pk)
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'object': self.object,
|
||||
})
|
||||
return context
|
|
@ -1,72 +1,205 @@
|
|||
<!DOCTYPE html>
|
||||
{% load i18n static %}
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
{% block head %}
|
||||
{% block meta %}
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="robots" content="NONE,NOARCHIVE" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="Pangea">
|
||||
{% endblock %}
|
||||
<title>{% block title %}{% if title %}{{ title }} – {% endif %}DeviceHub{% endblock %}</title>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<!-- Bootstrap core CSS -->
|
||||
{% block style %}
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
|
||||
<link rel="stylesheet" href= "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
|
||||
<link href="{% static "/css/bootstrap.min.css" %}" rel="stylesheet">
|
||||
|
||||
<title>{% block page_title %}{% endblock %} - Usody</title>
|
||||
<meta content="" name="description">
|
||||
<meta content="" name="keywords">
|
||||
<style>
|
||||
.bd-placeholder-img {
|
||||
font-size: 1.125rem;
|
||||
text-anchor: middle;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
<!-- Favicons -->
|
||||
<link href="{{ url_for('static', filename='img/favicon.png') }}" rel="icon">
|
||||
<link href="{{ url_for('static', filename='img/apple-touch-icon.png') }}" rel="apple-touch-icon">
|
||||
@media (min-width: 768px) {
|
||||
.bd-placeholder-img-lg {
|
||||
font-size: 3.5rem;
|
||||
}
|
||||
}
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
<!-- Google Fonts -->
|
||||
<link href="https://fonts.gstatic.com" rel="preconnect">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i|Nunito:300,300i,400,400i,600,600i,700,700i|Poppins:300,300i,400,400i,500,500i,600,600i,700,700i" rel="stylesheet">
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
<!-- JS Files -->
|
||||
<script src="{{ url_for('static', filename='js/jquery-3.6.0.min.js') }}"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/simple-datatables@5.0.3" type="text/javascript"></script>
|
||||
.main-content {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
footer {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<!-- Custom styles for this template -->
|
||||
<link href="{% static "/css/dashboard.css" %}" rel="stylesheet">
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
<header class="navbar navbar-dark sticky-top admin bg-green flex-md-nowrap p-0 shadow">
|
||||
<a class="navbar-brand col-md-3 col-lg-2 me-0 px-3" href="#">DEVICE HUB</a>
|
||||
<div class="navbar-nav navbar-sub-brand">
|
||||
PANGEA
|
||||
</div>
|
||||
<div class="navbar-nav">
|
||||
<div class="nav-item text-nowrap">
|
||||
<i id="user-avatar" class="bi bi-person-circle"></i>
|
||||
<a class="navbar-sub-brand px-3" href="#">{{ user.email }}</a>
|
||||
<a class="logout" href="{% url 'login:logout' %}">
|
||||
<i class="fa-solid fa-arrow-right-from-bracket"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Vendor CSS Files -->
|
||||
<link href="{{ url_for('static', filename='vendor/bootstrap/css/bootstrap.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ url_for('static', filename='vendor/bootstrap-icons/bootstrap-icons.css') }}" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/npm/simple-datatables@5.0.3/dist/style.css" rel="stylesheet" type="text/css">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
|
||||
<div class="position-sticky pt-5">
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item">
|
||||
<a class="admin {% if section == 'Devices' %}active {% endif %}nav-link fw-bold" data-bs-toggle="collapse" data-bs-target="#ul_devices" aria-expanded="false" aria-controls="ul_devices" href="javascript:void()">
|
||||
<i class="bi bi-laptop icon_sidebar"></i>
|
||||
{% trans 'Devices' %}
|
||||
</a>
|
||||
<ul class="flex-column mb-2 ul_sidebar accordion-collapse {% if section == 'People' %}expanded{% else %}collapse{% endif %}" id="ul_devices" data-bs-parent="#sidebarMenu">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if path == 'admin_people_list' %} active2{% endif %}" href="{% url 'dashboard:unassigned_devices' %}">
|
||||
{% trans 'Unassigned devices' %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if path == 'admin_people_new' %} active2{% endif %}" href="{# url 'idhub:admin_people_new' #}">
|
||||
{% trans 'All devices' %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="admin {% if section == 'People' %}active {% endif %}nav-link fw-bold" data-bs-toggle="collapse" data-bs-target="#ul_lots" aria-expanded="false" aria-controls="ul_lots" href="javascript:void()">
|
||||
<i class="bi bi-database icon_sidebar"></i>
|
||||
{% trans 'Lots' %}
|
||||
</a>
|
||||
<ul class="flex-column mb-2 ul_sidebar accordion-collapse {% if section == 'People' %}expanded{% else %}collapse{% endif %}" id="ul_lots" data-bs-parent="#sidebarMenu">
|
||||
<li class="nav-items">
|
||||
<a class="nav-link{% if path == 'admin_people_list' %} active2{% endif %}" href="{# url 'idhub:admin_people_list' #}">
|
||||
{% trans 'Incoming ' %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if path == 'admin_people_new' %} active2{% endif %}" href="{# url 'idhub:admin_people_new' #}">
|
||||
{% trans 'Outgoing ' %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if path == 'admin_people_new' %} active2{% endif %}" href="{# url 'idhub:admin_people_new' #}">
|
||||
{% trans 'Temporal ' %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="admin {% if section == 'People' %}active {% endif %}nav-link fw-bold" data-bs-toggle="collapse" data-bs-target="#ul_snapshots" aria-expanded="false" aria-controls="ul_snapshots" href="javascript:void()">
|
||||
<i class="bi bi-usb-drive icon_sidebar"></i>
|
||||
{% trans 'Snapshots' %}
|
||||
</a>
|
||||
<ul class="flex-column mb-2 ul_sidebar accordion-collapse {% if section == 'People' %}expanded{% else %}collapse{% endif %}" id="ul_snapshots" data-bs-parent="#sidebarMenu">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if path == 'admin_people_list' %} active2{% endif %}" href="{# url 'idhub:admin_people_list' #}">
|
||||
{% trans 'Upload one' %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if path == 'admin_people_list' %} active2{% endif %}" href="{# url 'idhub:admin_people_list' #}">
|
||||
{% trans 'Old snapshots' %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="admin {% if section == 'People' %}active {% endif %}nav-link fw-bold" data-bs-toggle="collapse" data-bs-target="#ul_placeholders" aria-expanded="false" aria-controls="ul_placeholders" href="javascript:void()">
|
||||
<i class="bi-menu-button-wide icon_sidebar"></i>
|
||||
{% trans 'Placeholders' %}
|
||||
</a>
|
||||
<ul class="flex-column mb-2 ul_sidebar accordion-collapse {% if section == 'People' %}expanded{% else %}collapse{% endif %}" id="ul_placeholders" data-bs-parent="#sidebarMenu">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if path == 'admin_people_list' %} active2{% endif %}" href="{# url 'idhub:admin_people_list' #}">
|
||||
{% trans 'Upload Spreadsheet' %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if path == 'admin_people_list' %} active2{% endif %}" href="{% url 'device:add' %}">
|
||||
{% trans 'Create one' %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
|
||||
{% block messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert {{ message.tags|default:'info' }} alert-dismissible fade show mt-3" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
|
||||
</button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endblock messages %}
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2">
|
||||
<h1 class="h2">{{ title }}</h1>
|
||||
</div>
|
||||
<div class="row border-bottom mb-3">
|
||||
<div class="col">
|
||||
<small style="color:#899bbd"><i>{{ breadcrumb }}</i></small>
|
||||
</div>
|
||||
<div class="btn-toolbar mb-2 mb-md-0">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Template Main CSS File -->
|
||||
<link href="{{ url_for('static', filename='css/style.css') }}" rel="stylesheet">
|
||||
<link href="{{ url_for('static', filename='css/devicehub.css') }}" rel="stylesheet">
|
||||
{% block content %}
|
||||
{% endblock content %}
|
||||
|
||||
<!-- =======================================================
|
||||
* Template Name: NiceAdmin - v2.2.0
|
||||
* Template URL: https://bootstrapmade.com/nice-admin-bootstrap-admin-html-template/
|
||||
* Author: BootstrapMade.com
|
||||
* License: https://bootstrapmade.com/license/
|
||||
======================================================== -->
|
||||
</head>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<body>
|
||||
|
||||
{% block body %}{% endblock %}
|
||||
|
||||
<a href="#" class="back-to-top d-flex align-items-center justify-content-center"><i class="bi bi-arrow-up-short"></i></a>
|
||||
|
||||
<!-- Vendor JS Files -->
|
||||
<script src="{{ url_for('static', filename='vendor/bootstrap/js/bootstrap.bundle.min.js') }}"></script>
|
||||
|
||||
<!-- Template Main JS File -->
|
||||
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
|
||||
|
||||
<!-- Api backend -->
|
||||
<script>
|
||||
const API_URLS = {
|
||||
Auth_Token: `Basic ${btoa("{{ current_user.token }}:")}`, //
|
||||
currentUserID: "{{ current_user.id }}",
|
||||
lots: "{# url_for('Lot.main') #}",
|
||||
lots_detail: "{# url_for('inventory.lotdevicelist', lot_id='ReplaceTEXT') #}",
|
||||
devices: "{{ url_for('Device.main') }}",
|
||||
devices_modify: "{# url_for('Lot.lot-device', id='UUID') #}",
|
||||
devices_detail: "{# url_for('inventory.device_details', id='ReplaceTEXT')#}"
|
||||
}
|
||||
</script>
|
||||
<script src="{{ url_for('static', filename='js/api.js') }}"></script>
|
||||
|
||||
</body>
|
||||
<!-- Footer -->
|
||||
<footer class="footer text-center mt-auto py-3">
|
||||
<div class="container">
|
||||
<span class="text-muted">{{ commit_id }}</span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{% block script %}
|
||||
<script src="{% static "js/jquery-3.3.1.slim.min.js" %}"></script>
|
||||
<script src="{% static "js/popper.min.js" %}"></script>
|
||||
<script src="{% static "js/bootstrap.min.js" %}"></script>
|
||||
{% block extrascript %}{% endblock %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,213 +0,0 @@
|
|||
{% load i18n static %}
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
{% block head %}
|
||||
{% block meta %}
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="robots" content="NONE,NOARCHIVE" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="Pangea">
|
||||
{% endblock %}
|
||||
<title>{% block title %}{% if title %}{{ title }} – {% endif %}DeviceHub{% endblock %}</title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
{% block style %}
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
|
||||
<link rel="stylesheet" href= "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
|
||||
<link href="{% static "/css/bootstrap.min.css" %}" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
.bd-placeholder-img {
|
||||
font-size: 1.125rem;
|
||||
text-anchor: middle;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.bd-placeholder-img-lg {
|
||||
font-size: 3.5rem;
|
||||
}
|
||||
}
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
footer {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<!-- Custom styles for this template -->
|
||||
<link href="{% static "/css/dashboard.css" %}" rel="stylesheet">
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
<header class="navbar navbar-dark sticky-top admin bg-green flex-md-nowrap p-0 shadow">
|
||||
<a class="navbar-brand col-md-3 col-lg-2 me-0 px-3" href="#">DEVICE HUB</a>
|
||||
<div class="navbar-nav navbar-sub-brand">
|
||||
PANGEA
|
||||
</div>
|
||||
<div class="navbar-nav">
|
||||
<div class="nav-item text-nowrap">
|
||||
<i id="user-avatar" class="bi bi-person-circle"></i>
|
||||
<a class="navbar-sub-brand px-3" href="#">{{ user.email }}</a>
|
||||
<a class="logout" href="{% url 'login:logout' %}">
|
||||
<i class="fa-solid fa-arrow-right-from-bracket"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
|
||||
<div class="position-sticky pt-5">
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item">
|
||||
<a class="admin nav-link {% if section == 'Home' %}active {% endif %}fw-bold" href="{% url 'dashboard:dashboard' %}">
|
||||
<i class="bi bi-house-door icon_sidebar"></i>
|
||||
{% trans 'Dashboard' %}
|
||||
</a>
|
||||
<hr />
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="admin {% if section == 'People' %}active {% endif %}nav-link fw-bold" data-bs-toggle="collapse" data-bs-target="#people" aria-expanded="false" aria-controls="people" href="javascript:void()">
|
||||
<i class="bi bi-people icon_sidebar"></i>
|
||||
{% trans 'Users' %}
|
||||
</a>
|
||||
<ul class="flex-column mb-2 ul_sidebar accordion-collapse {% if section == 'People' %}expanded{% else %}collapse{% endif %}" id="people" data-bs-parent="#sidebarMenu">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if path == 'admin_people_list' %} active2{% endif %}" href="{# url 'idhub:admin_people_list' #}">
|
||||
{% trans 'View users' %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if path == 'admin_people_new' %} active2{% endif %}" href="{# url 'idhub:admin_people_new' #}">
|
||||
{% trans 'Add user' %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="admin nav-link {% if section == 'AccessControl' %}active {% endif %}fw-bold" data-bs-toggle="collapse" data-bs-target="#control-access" aria-expanded="false" aria-controls="control-access" href="javascript:void()">
|
||||
<i class="fa-solid fa-arrow-right-from-bracket icon_sidebar"></i>
|
||||
{% trans 'Roles' %}
|
||||
</a>
|
||||
<ul class="flex-column mb-2 ul_sidebar accordion-collapse {% if section == 'AccessControl' %}expanded{% else %}collapse{% endif %}" id="control-access" data-bs-parent="#sidebarMenu">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if path == 'admin_roles' %} active2{% endif %}" href="{# url 'idhub:admin_roles' #}">
|
||||
{% trans 'Manage roles' %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if path == 'admin_services' %} active2{% endif %}" href="{# url 'idhub:admin_services' #}">
|
||||
{% trans 'Manage services' %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="admin nav-link {% if section == 'Credential' %}active {% endif %}fw-bold" data-bs-toggle="collapse" data-bs-target="#credential" aria-expanded="false" aria-controls="credential" href="javascript:void()">
|
||||
<i class="bi bi-patch-check icon_sidebar"></i>
|
||||
{% trans 'Credentials' %}
|
||||
</a>
|
||||
<ul class="flex-column mb-2 ul_sidebar accordion-collapse {% if section == 'Credential' %}expanded{% else %}collapse{% endif %}" id="credential" data-bs-parent="#sidebarMenu">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if path == 'admin_credentials' %} active2{% endif %}" href="{# url 'idhub:admin_credentials' #}">
|
||||
{% trans 'View credentials' %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a id="wallet" class="nav-link" data-bs-toggle="collapse" data-bs-target="#lwallet" aria-expanded="false" aria-controls="lwallet" href="javascript:void()">
|
||||
{% trans "Organization's wallet" %}
|
||||
</a>
|
||||
<ul class="flex-column mb-2 accordion-collapse {% if wallet %}expanded{% else %}collapse{% endif %}" id="lwallet" data-bs-parent="#wallet">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if path == 'admin_dids' %} active2{% endif %}" href="{# url 'idhub:admin_dids' #}">
|
||||
{% trans 'Manage Identities (DIDs)' %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if path == 'admin_wallet_credentials' %} active2{% endif %}" href="{# url 'idhub:admin_wallet_credentials' #}">
|
||||
{% trans 'View org. credentials' %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if path == 'admin_wallet_config_issue' %} active2{% endif %}" href="{# url 'idhub:admin_wallet_config_issue' #}">
|
||||
{% trans 'Configure credential issuance' %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="admin nav-link {% if section == 'Templates' %}active {% endif %}fw-bold" href="{# url 'idhub:admin_schemas' #}">
|
||||
<i class="bi bi-file-earmark-text icon_sidebar"></i>
|
||||
{% trans 'Templates' %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="admin nav-link {% if section == 'ImportExport' %}active {% endif %}fw-bold" href="{# url 'idhub:admin_import' #}">
|
||||
<i class="bi bi-arrow-down-square icon_sidebar"></i>
|
||||
{% trans 'Data' %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
|
||||
{% block messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert {{ message.tags|default:'info' }} alert-dismissible fade show mt-3" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
|
||||
</button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endblock messages %}
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||
<h1 class="h2">{{ title }}</h1>
|
||||
<div class="btn-toolbar mb-2 mb-md-0">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% block content %}
|
||||
{% endblock content %}
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="footer text-center mt-auto py-3">
|
||||
<div class="container">
|
||||
<span class="text-muted">{{ commit_id }}</span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{% block script %}
|
||||
<script src="{% static "js/jquery-3.3.1.slim.min.js" %}"></script>
|
||||
<script src="{% static "js/popper.min.js" %}"></script>
|
||||
<script src="{% static "js/bootstrap.min.js" %}"></script>
|
||||
{% block extrascript %}{% endblock %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
</html>
|
49
dashboard/templates/unassigned_devices.html
Normal file
49
dashboard/templates/unassigned_devices.html
Normal file
|
@ -0,0 +1,49 @@
|
|||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ subtitle }}</h3>
|
||||
</div>
|
||||
<div class="col text-center">
|
||||
<a href="{# url 'idhub:admin_people_edit' object.id #}" type="button" class="btn btn-green-admin">
|
||||
<i class="bi bi-folder2"></i>
|
||||
{% trans 'Lots' %}
|
||||
</a>
|
||||
<a href="{# url 'idhub:admin_people_edit' object.id #}" type="button" class="btn btn-green-admin">
|
||||
<i class="bi bi-plus"></i>
|
||||
{% trans 'Actions' %}
|
||||
</a>
|
||||
<a href="{# url 'idhub:admin_people_activate' object.id #}" type="button" class="btn btn-green-admin">
|
||||
<i class="bi bi-reply"></i>
|
||||
{% trans 'Exports' %}
|
||||
</a>
|
||||
<a href="#" type="button" class="btn btn-green-admin">
|
||||
<i class="bi bi-tag"></i>
|
||||
{% trans 'Labels' %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dataTable-container">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" data-sortable="">
|
||||
<a class="dataTable-sorter" href="#">Title</a>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{% for dev in devices %}
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{% url 'device:details' dev.pk %}">{{ dev.type }} {{ dev.manufacturer }} {{ dev.model }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,8 +1,8 @@
|
|||
from django.urls import path
|
||||
from dashboard.views import DashboardView
|
||||
from dashboard import views
|
||||
|
||||
app_name = 'dashboard'
|
||||
|
||||
urlpatterns = [
|
||||
path("", DashboardView.as_view(), name="dashboard"),
|
||||
path("", views.UnassignedDevicesView.as_view(), name="unassigned_devices"),
|
||||
]
|
||||
|
|
|
@ -1,46 +1,19 @@
|
|||
from django.views import View
|
||||
from django.template.loader import get_template
|
||||
from django.http import HttpResponse
|
||||
from django.urls import resolve
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.views.generic.base import TemplateView
|
||||
from dashboard.mixins import DashboardView
|
||||
from device.models import Device
|
||||
|
||||
|
||||
class Http403(PermissionDenied):
|
||||
status_code = 403
|
||||
default_detail = _('Permission denied. User is not authenticated')
|
||||
default_code = 'forbidden'
|
||||
class UnassignedDevicesView(DashboardView, TemplateView):
|
||||
template_name = "unassigned_devices.html"
|
||||
section = "Unassigned"
|
||||
title = _("Unassigned Devices")
|
||||
breadcrumb = "Devices / Unassigned Devices"
|
||||
|
||||
def __init__(self, details=None, code=None):
|
||||
if details is not None:
|
||||
self.detail = details or self.default_details
|
||||
if code is not None:
|
||||
self.code = code or self.default_code
|
||||
|
||||
|
||||
class DashboardView(LoginRequiredMixin, View):
|
||||
login_url = "/login/"
|
||||
template_name = "dashboard.html"
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
|
||||
template = get_template(
|
||||
self.template_name,
|
||||
).render()
|
||||
return HttpResponse(template)
|
||||
|
||||
# response = super().get(request, *args, **kwargs)
|
||||
# return response
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
devices = Device.objects.filter(owner=self.request.user)
|
||||
context.update({
|
||||
# 'title': self.title,
|
||||
# 'subtitle': self.subtitle,
|
||||
# 'icon': self.icon,
|
||||
# 'section': self.section,
|
||||
'path': resolve(self.request.path).url_name,
|
||||
# 'user': self.request.user,
|
||||
'devices': devices,
|
||||
})
|
||||
return context
|
||||
|
|
42
device/forms.py
Normal file
42
device/forms.py
Normal file
|
@ -0,0 +1,42 @@
|
|||
from django import forms
|
||||
# from django.utils.translation import gettext_lazy as _
|
||||
# from django.core.exceptions import ValidationError
|
||||
# from user.models import User
|
||||
from device.models import (
|
||||
Device,
|
||||
PhysicalProperties
|
||||
)
|
||||
|
||||
|
||||
class DeviceForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = Device
|
||||
fields = [
|
||||
'type',
|
||||
"model",
|
||||
"manufacturer",
|
||||
"serial_number",
|
||||
"part_number",
|
||||
"brand",
|
||||
"generation",
|
||||
"version",
|
||||
"production_date",
|
||||
"variant",
|
||||
"family",
|
||||
]
|
||||
|
||||
|
||||
class PhysicalPropsForm(forms.Form):
|
||||
|
||||
class Meta:
|
||||
model = PhysicalProperties
|
||||
fields = [
|
||||
"device",
|
||||
"weight",
|
||||
"width",
|
||||
"height",
|
||||
"depth",
|
||||
"color",
|
||||
"image",
|
||||
]
|
|
@ -0,0 +1,33 @@
|
|||
# Generated by Django 5.0.6 on 2024-07-03 11:07
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("device", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="device",
|
||||
name="brand",
|
||||
field=models.CharField(blank=True, max_length=64, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="device",
|
||||
name="devicehub_id",
|
||||
field=models.CharField(blank=True, max_length=64, null=True, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="device",
|
||||
name="variant",
|
||||
field=models.CharField(blank=True, max_length=64, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="device",
|
||||
name="version",
|
||||
field=models.CharField(blank=True, max_length=64, null=True),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,73 @@
|
|||
# Generated by Django 5.0.6 on 2024-07-03 12:33
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("device", "0002_alter_device_brand_alter_device_devicehub_id_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name="component",
|
||||
name="type",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="computer",
|
||||
name="type",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="datastorage",
|
||||
name="type",
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="computer",
|
||||
name="chassis",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
choices=[
|
||||
("Tower", "Tower"),
|
||||
("All in one", "Allinone"),
|
||||
("Microtower", "Microtower"),
|
||||
("Netbook", "Netbook"),
|
||||
("Laptop", "Laptop"),
|
||||
("Tablet", "Tabler"),
|
||||
("Server", "Server"),
|
||||
("Non-physical device", "Virtual"),
|
||||
],
|
||||
max_length=32,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="computer",
|
||||
name="sku",
|
||||
field=models.CharField(blank=True, max_length=32, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="device",
|
||||
name="type",
|
||||
field=models.CharField(
|
||||
choices=[
|
||||
("Desktop", "Desktop"),
|
||||
("Laptop", "Laptop"),
|
||||
("Server", "Server"),
|
||||
("GraphicCard", "Graphiccard"),
|
||||
("HardDrive", "Harddrive"),
|
||||
("SolidStateDrive", "Solidstatedrive"),
|
||||
("Motherboard", "Motherboard"),
|
||||
("NetworkAdapter", "Networkadapter"),
|
||||
("Processor", "Processor"),
|
||||
("RamModule", "Rammodule"),
|
||||
("SoundCard", "Soundcard"),
|
||||
("Display", "Display"),
|
||||
("Battery", "Battery"),
|
||||
("Camera", "Camera"),
|
||||
],
|
||||
default="Laptop",
|
||||
max_length=32,
|
||||
),
|
||||
),
|
||||
]
|
|
@ -3,23 +3,36 @@ from user.models import User
|
|||
from utils.constants import STR_SM_SIZE, STR_SIZE
|
||||
|
||||
|
||||
# Create your models here.
|
||||
|
||||
|
||||
class Device(models.Model):
|
||||
class Types(models.TextChoices):
|
||||
DESKTOP = "Desktop"
|
||||
LAPTOP = "Laptop"
|
||||
SERVER = "Server"
|
||||
GRAPHICCARD = "GraphicCard"
|
||||
HARDDRIVE = "HardDrive"
|
||||
SOLIDSTATEDRIVE = "SolidStateDrive"
|
||||
MOTHERBOARD = "Motherboard"
|
||||
NETWORKADAPTER = "NetworkAdapter"
|
||||
PROCESSOR = "Processor"
|
||||
RAMMODULE = "RamModule"
|
||||
SOUNDCARD = "SoundCard"
|
||||
DISPLAY = "Display"
|
||||
BATTERY = "Battery"
|
||||
CAMERA = "Camera"
|
||||
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
updated = models.DateTimeField(auto_now=True)
|
||||
type = models.CharField(max_length=STR_SM_SIZE)
|
||||
type = models.CharField(max_length=STR_SM_SIZE, choices=Types, default=Types.LAPTOP)
|
||||
model = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
manufacturer = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
serial_number = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
part_number = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
brand = models.TextField(blank=True, null=True)
|
||||
brand = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
generation = models.SmallIntegerField(blank=True, null=True)
|
||||
version = models.TextField(blank=True, null=True)
|
||||
version = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
production_date = models.DateTimeField(blank=True, null=True)
|
||||
variant = models.TextField(blank=True, null=True)
|
||||
devicehub_id = models.TextField(unique=True, blank=True, null=True)
|
||||
variant = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
devicehub_id = models.CharField(max_length=STR_SIZE, unique=True, blank=True, null=True)
|
||||
dhid_bk = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
phid_bk = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
family = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
|
@ -40,33 +53,30 @@ class PhysicalProperties(models.Model):
|
|||
|
||||
|
||||
class Computer(models.Model):
|
||||
class Types(models.TextChoices):
|
||||
DESKTOP = "Desktop"
|
||||
LAPTOP = "Laptop"
|
||||
class Chassis(models.TextChoices):
|
||||
TOWER = 'Tower'
|
||||
ALLINONE = 'All in one'
|
||||
MICROTOWER = 'Microtower'
|
||||
NETBOOK = 'Netbook'
|
||||
LAPTOP = 'Laptop'
|
||||
TABLER = 'Tablet'
|
||||
SERVER = "Server"
|
||||
VIRTUAL = 'Non-physical device'
|
||||
|
||||
|
||||
device = models.OneToOneField(Device, models.CASCADE, primary_key=True)
|
||||
chassis = models.TextField(blank=True, null=True)
|
||||
chassis = models.CharField(
|
||||
blank=True,
|
||||
null=True,
|
||||
max_length=STR_SM_SIZE,
|
||||
choices=Chassis
|
||||
)
|
||||
system_uuid = models.UUIDField()
|
||||
sku = models.TextField(blank=True, null=True)
|
||||
type = models.CharField(max_length=STR_SM_SIZE, choices=Types, default=Types.LAPTOP)
|
||||
sku = models.CharField(max_length=STR_SM_SIZE, blank=True, null=True)
|
||||
|
||||
|
||||
class Component(models.Model):
|
||||
class Types(models.TextChoices):
|
||||
GRAPHICCARD = "GraphicCard"
|
||||
DATASTORAGE = "DataStorage"
|
||||
MOTHERBOARD = "Motherboard"
|
||||
NETWORKADAPTER = "NetworkAdapter"
|
||||
PROCESSOR = "Processor"
|
||||
RAMMODULE = "RamModule"
|
||||
SOUNDCARD = "SoundCard"
|
||||
DISPLAY = "Display"
|
||||
BATTERY = "Battery"
|
||||
CAMERA = "Camera"
|
||||
|
||||
device = models.OneToOneField(Device, models.CASCADE, primary_key=True)
|
||||
type = models.CharField(max_length=STR_SM_SIZE, choices=Types)
|
||||
computer = models.OneToOneField(Computer, models.CASCADE, null=True)
|
||||
|
||||
|
||||
|
@ -82,14 +92,9 @@ class DataStorage(models.Model):
|
|||
PCI = 'PCI'
|
||||
NVME = 'NVME'
|
||||
|
||||
class Type(models.TextChoices):
|
||||
HARDDRIVE = "HardDrive"
|
||||
SOLIDSTATEDRIVE = "SolidStateDrive"
|
||||
|
||||
component = models.OneToOneField(Component, models.CASCADE)
|
||||
size = models.IntegerField(blank=True, null=True)
|
||||
interface = models.CharField(max_length=STR_SM_SIZE, choices=Interface)
|
||||
type = models.CharField(max_length=STR_SM_SIZE, choices=Type)
|
||||
component = models.OneToOneField(Component, models.CASCADE)
|
||||
|
||||
|
||||
class Motherboard(models.Model):
|
||||
|
|
262
device/templates/details.html
Normal file
262
device/templates/details.html
Normal file
|
@ -0,0 +1,262 @@
|
|||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ object.pk }}</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="nav nav-tabs nav-tabs-bordered">
|
||||
<li class="nav-items">
|
||||
<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#details">General details</button>
|
||||
</li>
|
||||
<li class="nav-items">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#physicalproperties">Physical properties</button>
|
||||
</li>
|
||||
<li class="nav-items">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#documents">Documents</button>
|
||||
</li>
|
||||
<li class="nav-items">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#lots">Lots</button>
|
||||
</li>
|
||||
<li class="nav-items">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#status">Status</button>
|
||||
</li>
|
||||
<li class="nav-items">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#components">Components</button>
|
||||
</li>
|
||||
<li class="nav-items">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#traceabiliy">Traceability log</button>
|
||||
</li>
|
||||
<li class="nav-items">
|
||||
<a class="nav-link" href="">Web</a>
|
||||
</li>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-content pt-2">
|
||||
|
||||
<div class="tab-pane fade show active" id="details">
|
||||
<h5 class="card-title">Details</h5>
|
||||
<div class="row mb-3">
|
||||
<div class="col-lg-3 col-md-4 label ">
|
||||
(<a href="/inventory/device/edit/4W8D3/">Edit Device</a>)
|
||||
</div>
|
||||
<div class="col-lg-9 col-md-8">
|
||||
{%if object.hid %}Snapshot{% else %}Placeholder{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">Phid</div>
|
||||
<div class="col-lg-9 col-md-8">{{ object.id }}</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">Id device internal</div>
|
||||
<div class="col-lg-9 col-md-8"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">Type</div>
|
||||
<div class="col-lg-9 col-md-8">{{ object.type }}</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label">Manufacturer</div>
|
||||
<div class="col-lg-9 col-md-8">{{ object.manufacturer|default:"" }}</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label">Model</div>
|
||||
<div class="col-lg-9 col-md-8">{{ object.model|default:"" }}</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label">Part Number</div>
|
||||
<div class="col-lg-9 col-md-8">{{ object.part_number|default:"" }}</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label">Serial Number</div>
|
||||
<div class="col-lg-9 col-md-8">{{ object.serial_number|default:"" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade profile-overview" id="physicalproperties">
|
||||
<h5 class="card-title">Physical Properties</h5>
|
||||
<div class="row mb-3">
|
||||
<div class="col-lg-3 col-md-4 label ">
|
||||
<a href="{% url 'device:details' object.pk %}">{{ object.type }} {{ object.manufacturer }} {{ object.model }}</a>
|
||||
<br>
|
||||
<a href="{% url 'device:physical_edit' object.pk %}">{{ object.type }} {{ object.manufacturer }} {{ object.model }}</a>
|
||||
<br>
|
||||
(<a href="{# url('device:physical_edit', object.id) #}">Edit Physical Properties</a>)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-lg-3 col-md-4 label ">
|
||||
Weight:
|
||||
</div>
|
||||
<div class="col-lg-9 col-md-8">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">width:</div>
|
||||
<div class="col-lg-9 col-md-8"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">height:</div>
|
||||
<div class="col-lg-9 col-md-8"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">depth:</div>
|
||||
<div class="col-lg-9 col-md-8"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">color:</div>
|
||||
<div class="col-lg-9 col-md-8"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">image:</div>
|
||||
<div class="col-lg-9 col-md-8"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="tab-pane fade profile-overview" id="lots">
|
||||
<h5 class="card-title">Incoming Lots</h5>
|
||||
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
|
||||
<h5 class="card-title">Outgoing Lots</h5>
|
||||
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
|
||||
<h5 class="card-title">Temporary Lots</h5>
|
||||
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade profile-overview" id="documents">
|
||||
<div class="btn-group dropdown ml-1 mt-1" uib-dropdown="">
|
||||
<a href="/inventory/device/4W8D3/document/add/" class="btn btn-primary">
|
||||
<i class="bi bi-plus"></i>
|
||||
Add new document
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<h5 class="card-title">Documents</h5>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">File</th>
|
||||
<th scope="col">Type</th>
|
||||
<th scope="col">Description</th>
|
||||
<th scope="col" data-type="date" data-format="YYYY-MM-DD hh:mm">Uploaded on</th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade profile-overview" id="status">
|
||||
<h5 class="card-title">Status Details</h5>
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label">Physical State</div>
|
||||
<div class="col-lg-9 col-md-8">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label">Lifecycle State</div>
|
||||
<div class="col-lg-9 col-md-8">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label">Allocated State</div>
|
||||
<div class="col-lg-9 col-md-8">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade profile-overview" id="traceability">
|
||||
<h5 class="card-title">Traceability log Details</h5>
|
||||
<div class="list-group col-6">
|
||||
|
||||
<div class="list-group-item d-flex justify-content-between align-items-center">
|
||||
Snapshot ✓
|
||||
<small class="text-muted">14:07 23-06-2024</small>
|
||||
</div>
|
||||
|
||||
<div class="list-group-item d-flex justify-content-between align-items-center">
|
||||
EraseCrypto ✓
|
||||
<small class="text-muted">14:07 23-06-2024</small>
|
||||
</div>
|
||||
|
||||
<div class="list-group-item d-flex justify-content-between align-items-center">
|
||||
EraseCrypto ✓
|
||||
<small class="text-muted">14:07 23-06-2024</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade profile-overview" id="components">
|
||||
<h5 class="card-title">Components Snapshot</h5>
|
||||
<div class="list-group col-6">
|
||||
|
||||
<div class="list-group-item">
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<h5 class="mb-1">Motherboard</h5>
|
||||
<small class="text-muted">14:07 23-06-2024</small>
|
||||
</div>
|
||||
<p class="mb-1">
|
||||
hp<br />
|
||||
890e<br />
|
||||
</p>
|
||||
<small class="text-muted">
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div class="list-group-item">
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<h5 class="mb-1">NetworkAdapter</h5>
|
||||
<small class="text-muted">14:07 23-06-2024</small>
|
||||
</div>
|
||||
<p class="mb-1">
|
||||
realtek semiconductor co., ltd.<br />
|
||||
rtl8852ae 802.11ax pcie wireless network adapter<br />
|
||||
</p>
|
||||
<small class="text-muted">
|
||||
</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
32
device/templates/new_device.html
Normal file
32
device/templates/new_device.html
Normal file
|
@ -0,0 +1,32 @@
|
|||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ subtitle }}</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% load django_bootstrap5 %}
|
||||
<form role="form" method="post">
|
||||
{% csrf_token %}
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-danger alert-icon alert-icon-border alert-dismissible" role="alert">
|
||||
<div class="icon"><span class="mdi mdi-close-circle-o"></span></div>
|
||||
<div class="message">
|
||||
{% for field, error in form.errors.items %}
|
||||
{{ error }}<br />
|
||||
{% endfor %}
|
||||
<button class="btn-close" type="button" data-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% bootstrap_form form %}
|
||||
<div class="form-actions-no-box">
|
||||
<a class="btn btn-grey" href="{% url 'dashboard:unassigned_devices' %}">{% translate "Cancel" %}</a>
|
||||
<input class="btn btn-green-admin" type="submit" name="submit" value="{% translate 'Save' %}" />
|
||||
</div>
|
||||
|
||||
</form>
|
||||
{% endblock %}
|
246
device/templates/physical_properties.html
Normal file
246
device/templates/physical_properties.html
Normal file
|
@ -0,0 +1,246 @@
|
|||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ object.pk }}</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="nav nav-tabs nav-tabs-bordered">
|
||||
<li class="nav-items">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#details">General details</button>
|
||||
</li>
|
||||
<li class="nav-items">
|
||||
<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#physicalproperties">Physical properties</button>
|
||||
</li>
|
||||
<li class="nav-items">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#documents">Documents</button>
|
||||
</li>
|
||||
<li class="nav-items">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#lots">Lots</button>
|
||||
</li>
|
||||
<li class="nav-items">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#status">Status</button>
|
||||
</li>
|
||||
<li class="nav-items">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#components">Components</button>
|
||||
</li>
|
||||
<li class="nav-items">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#traceabiliy">Traceability log</button>
|
||||
</li>
|
||||
<li class="nav-items">
|
||||
<a class="nav-link" href="">Web</a>
|
||||
</li>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-content pt-2">
|
||||
|
||||
<div class="tab-pane fade profile-overview" id="details">
|
||||
<h5 class="card-title">Details</h5>
|
||||
<div class="row mb-3">
|
||||
<div class="col-lg-3 col-md-4 label ">
|
||||
(<a href="/inventory/device/edit/4W8D3/">Edit Device</a>)
|
||||
</div>
|
||||
<div class="col-lg-9 col-md-8">
|
||||
{%if object.hid %}Snapshot{% else %}Placeholder{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">Phid</div>
|
||||
<div class="col-lg-9 col-md-8">{{ object.id }}</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">Id device internal</div>
|
||||
<div class="col-lg-9 col-md-8"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">Type</div>
|
||||
<div class="col-lg-9 col-md-8">{{ object.type }}</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label">Manufacturer</div>
|
||||
<div class="col-lg-9 col-md-8">{{ object.manufacturer|default:"" }}</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label">Model</div>
|
||||
<div class="col-lg-9 col-md-8">{{ object.model|default:"" }}</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label">Part Number</div>
|
||||
<div class="col-lg-9 col-md-8">{{ object.part_number|default:"" }}</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label">Serial Number</div>
|
||||
<div class="col-lg-9 col-md-8">{{ object.serial_number|default:"" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade show active" id="physicalproperties">
|
||||
<h5 class="card-title">Physical Properties</h5>
|
||||
<div class="row mb-3">
|
||||
<div class="col-lg-3 col-md-4 label ">
|
||||
<a href="{% url 'device:details' object.pk %}">{{ object.type }} {{ object.manufacturer }} {{ object.model }}</a>
|
||||
<br>
|
||||
<a href="{% url 'device:physical_edit' object.pk %}">{{ object.type }} {{ object.manufacturer }} {{ object.model }}</a>
|
||||
<br>
|
||||
(<a href="{# url('device:physical_edit', object.id) #}">Edit Physical Properties</a>)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-lg-3 col-md-4 label ">
|
||||
{{ form }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">color:</div>
|
||||
<div class="col-lg-9 col-md-8"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">image:</div>
|
||||
<div class="col-lg-9 col-md-8"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="tab-pane fade profile-overview" id="lots">
|
||||
<h5 class="card-title">Incoming Lots</h5>
|
||||
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
|
||||
<h5 class="card-title">Outgoing Lots</h5>
|
||||
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
|
||||
<h5 class="card-title">Temporary Lots</h5>
|
||||
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade profile-overview" id="documents">
|
||||
<div class="btn-group dropdown ml-1 mt-1" uib-dropdown="">
|
||||
<a href="/inventory/device/4W8D3/document/add/" class="btn btn-primary">
|
||||
<i class="bi bi-plus"></i>
|
||||
Add new document
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<h5 class="card-title">Documents</h5>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">File</th>
|
||||
<th scope="col">Type</th>
|
||||
<th scope="col">Description</th>
|
||||
<th scope="col" data-type="date" data-format="YYYY-MM-DD hh:mm">Uploaded on</th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade profile-overview" id="status">
|
||||
<h5 class="card-title">Status Details</h5>
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label">Physical State</div>
|
||||
<div class="col-lg-9 col-md-8">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label">Lifecycle State</div>
|
||||
<div class="col-lg-9 col-md-8">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label">Allocated State</div>
|
||||
<div class="col-lg-9 col-md-8">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade profile-overview" id="traceability">
|
||||
<h5 class="card-title">Traceability log Details</h5>
|
||||
<div class="list-group col-6">
|
||||
|
||||
<div class="list-group-item d-flex justify-content-between align-items-center">
|
||||
Snapshot ✓
|
||||
<small class="text-muted">14:07 23-06-2024</small>
|
||||
</div>
|
||||
|
||||
<div class="list-group-item d-flex justify-content-between align-items-center">
|
||||
EraseCrypto ✓
|
||||
<small class="text-muted">14:07 23-06-2024</small>
|
||||
</div>
|
||||
|
||||
<div class="list-group-item d-flex justify-content-between align-items-center">
|
||||
EraseCrypto ✓
|
||||
<small class="text-muted">14:07 23-06-2024</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade profile-overview" id="components">
|
||||
<h5 class="card-title">Components Snapshot</h5>
|
||||
<div class="list-group col-6">
|
||||
|
||||
<div class="list-group-item">
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<h5 class="mb-1">Motherboard</h5>
|
||||
<small class="text-muted">14:07 23-06-2024</small>
|
||||
</div>
|
||||
<p class="mb-1">
|
||||
hp<br />
|
||||
890e<br />
|
||||
</p>
|
||||
<small class="text-muted">
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div class="list-group-item">
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<h5 class="mb-1">NetworkAdapter</h5>
|
||||
<small class="text-muted">14:07 23-06-2024</small>
|
||||
</div>
|
||||
<p class="mb-1">
|
||||
realtek semiconductor co., ltd.<br />
|
||||
rtl8852ae 802.11ax pcie wireless network adapter<br />
|
||||
</p>
|
||||
<small class="text-muted">
|
||||
</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
10
device/urls.py
Normal file
10
device/urls.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
from django.urls import path
|
||||
from device import views
|
||||
|
||||
app_name = 'device'
|
||||
|
||||
urlpatterns = [
|
||||
path("add/", views.NewDeviceView.as_view(), name="add"),
|
||||
path("<int:pk>/", views.DetailsView.as_view(), name="details"),
|
||||
path("physical/<int:pk>/", views.PhysicalView.as_view(), name="physical_edit"),
|
||||
]
|
|
@ -1,3 +1,81 @@
|
|||
from django.shortcuts import render
|
||||
from django.urls import reverse_lazy
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic.edit import (
|
||||
CreateView,
|
||||
UpdateView,
|
||||
)
|
||||
from dashboard.mixins import DashboardView, DetailsMixin
|
||||
from device.forms import DeviceForm, PhysicalPropsForm
|
||||
from device.models import Device, PhysicalProperties
|
||||
|
||||
|
||||
class NewDeviceView(DashboardView, CreateView):
|
||||
template_name = "new_device.html"
|
||||
title = _("New Device")
|
||||
breadcrumb = "Device / New Device"
|
||||
form_class = DeviceForm
|
||||
success_url = reverse_lazy('dashboard:unassigned_devices')
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.owner = self.request.user
|
||||
response = super().form_valid(form)
|
||||
PhysicalProperties.objects.create(device=form.instance)
|
||||
return response
|
||||
|
||||
|
||||
class DetailsView(DetailsMixin):
|
||||
template_name = "details.html"
|
||||
title = _("Device")
|
||||
breadcrumb = "Device / Details"
|
||||
model = Device
|
||||
|
||||
|
||||
class PhysicalView(DashboardView, UpdateView):
|
||||
template_name = "physical_properties.html"
|
||||
title = _("Physical Properties")
|
||||
breadcrumb = "Device / Physical properties"
|
||||
form_class = PhysicalPropsForm
|
||||
success_url = reverse_lazy('dashboard:unassigned_devices')
|
||||
model = PhysicalProperties
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
pk = kwargs['pk']
|
||||
self.device = get_object_or_404(Device, pk=pk)
|
||||
try:
|
||||
self.object = self.device.physicalproperties
|
||||
except Exception:
|
||||
self.object = PhysicalProperties.objects.create(device=self.device)
|
||||
self.initial.update({'instance': self.object})
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def get_form(self, form_class=None):
|
||||
"""Return an instance of the form to be used in this view."""
|
||||
if form_class is None:
|
||||
form_class = self.get_form_class()
|
||||
# import pdb; pdb.set_trace()
|
||||
return form_class(**self.get_form_kwargs())
|
||||
|
||||
def get_form_kwargs(self):
|
||||
"""Return the keyword arguments for instantiating the form."""
|
||||
kwargs = {
|
||||
"initial": self.get_initial(),
|
||||
"prefix": self.get_prefix(),
|
||||
}
|
||||
|
||||
if self.request.method in ("POST", "PUT"):
|
||||
kwargs.update(
|
||||
{
|
||||
"data": self.request.POST,
|
||||
"files": self.request.FILES,
|
||||
}
|
||||
)
|
||||
return kwargs
|
||||
|
||||
def form_valid(self, form):
|
||||
self.success_url = reverse_lazy('device:details', self.device.id)
|
||||
form.instance.owner = self.request.user
|
||||
response = super().form_valid(form)
|
||||
return response
|
||||
|
||||
|
||||
# Create your views here.
|
||||
|
|
|
@ -21,4 +21,5 @@ urlpatterns = [
|
|||
# path('api/', include('snapshot.urls')),
|
||||
path("", include("login.urls")),
|
||||
path("dashboard/", include("dashboard.urls")),
|
||||
path("device/", include("device.urls")),
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue