add device details
This commit is contained in:
parent
07d0aa6f1c
commit
df63af3ee0
|
@ -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">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
{% block head %}
|
||||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
{% 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>
|
||||||
|
|
||||||
<title>{% block page_title %}{% endblock %} - Usody</title>
|
<!-- Bootstrap core CSS -->
|
||||||
<meta content="" name="description">
|
{% block style %}
|
||||||
<meta content="" name="keywords">
|
<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">
|
||||||
|
|
||||||
<!-- Favicons -->
|
<style>
|
||||||
<link href="{{ url_for('static', filename='img/favicon.png') }}" rel="icon">
|
.bd-placeholder-img {
|
||||||
<link href="{{ url_for('static', filename='img/apple-touch-icon.png') }}" rel="apple-touch-icon">
|
font-size: 1.125rem;
|
||||||
|
text-anchor: middle;
|
||||||
<!-- Google Fonts -->
|
-webkit-user-select: none;
|
||||||
<link href="https://fonts.gstatic.com" rel="preconnect">
|
-moz-user-select: none;
|
||||||
<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">
|
user-select: none;
|
||||||
|
|
||||||
<!-- 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>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 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">
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 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">
|
|
||||||
|
|
||||||
<!-- =======================================================
|
|
||||||
* 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>
|
|
||||||
|
|
||||||
<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>
|
|
||||||
|
|
||||||
|
@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 {% 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>
|
||||||
|
|
||||||
|
{% 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>
|
</body>
|
||||||
|
|
||||||
</html>
|
</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>
|
|
|
@ -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 django.urls import path
|
||||||
from dashboard.views import DashboardView
|
from dashboard import views
|
||||||
|
|
||||||
app_name = 'dashboard'
|
app_name = 'dashboard'
|
||||||
|
|
||||||
urlpatterns = [
|
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.utils.translation import gettext_lazy as _
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.views.generic.base import TemplateView
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from dashboard.mixins import DashboardView
|
||||||
|
from device.models import Device
|
||||||
|
|
||||||
|
|
||||||
class Http403(PermissionDenied):
|
class UnassignedDevicesView(DashboardView, TemplateView):
|
||||||
status_code = 403
|
template_name = "unassigned_devices.html"
|
||||||
default_detail = _('Permission denied. User is not authenticated')
|
section = "Unassigned"
|
||||||
default_code = 'forbidden'
|
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):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
|
devices = Device.objects.filter(owner=self.request.user)
|
||||||
context.update({
|
context.update({
|
||||||
# 'title': self.title,
|
'devices': devices,
|
||||||
# 'subtitle': self.subtitle,
|
|
||||||
# 'icon': self.icon,
|
|
||||||
# 'section': self.section,
|
|
||||||
'path': resolve(self.request.path).url_name,
|
|
||||||
# 'user': self.request.user,
|
|
||||||
})
|
})
|
||||||
return context
|
return context
|
||||||
|
|
|
@ -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
|
from utils.constants import STR_SM_SIZE, STR_SIZE
|
||||||
|
|
||||||
|
|
||||||
# Create your models here.
|
|
||||||
|
|
||||||
|
|
||||||
class Device(models.Model):
|
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)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
updated = models.DateTimeField(auto_now=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)
|
model = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||||
manufacturer = 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)
|
serial_number = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||||
part_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)
|
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)
|
production_date = models.DateTimeField(blank=True, null=True)
|
||||||
variant = models.TextField(blank=True, null=True)
|
variant = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||||
devicehub_id = models.TextField(unique=True, 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)
|
dhid_bk = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||||
phid_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)
|
family = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||||
|
@ -40,33 +53,30 @@ class PhysicalProperties(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class Computer(models.Model):
|
class Computer(models.Model):
|
||||||
class Types(models.TextChoices):
|
class Chassis(models.TextChoices):
|
||||||
DESKTOP = "Desktop"
|
TOWER = 'Tower'
|
||||||
LAPTOP = "Laptop"
|
ALLINONE = 'All in one'
|
||||||
|
MICROTOWER = 'Microtower'
|
||||||
|
NETBOOK = 'Netbook'
|
||||||
|
LAPTOP = 'Laptop'
|
||||||
|
TABLER = 'Tablet'
|
||||||
SERVER = "Server"
|
SERVER = "Server"
|
||||||
|
VIRTUAL = 'Non-physical device'
|
||||||
|
|
||||||
|
|
||||||
device = models.OneToOneField(Device, models.CASCADE, primary_key=True)
|
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()
|
system_uuid = models.UUIDField()
|
||||||
sku = models.TextField(blank=True, null=True)
|
sku = models.CharField(max_length=STR_SM_SIZE, blank=True, null=True)
|
||||||
type = models.CharField(max_length=STR_SM_SIZE, choices=Types, default=Types.LAPTOP)
|
|
||||||
|
|
||||||
|
|
||||||
class Component(models.Model):
|
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)
|
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)
|
computer = models.OneToOneField(Computer, models.CASCADE, null=True)
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,14 +92,9 @@ class DataStorage(models.Model):
|
||||||
PCI = 'PCI'
|
PCI = 'PCI'
|
||||||
NVME = 'NVME'
|
NVME = 'NVME'
|
||||||
|
|
||||||
class Type(models.TextChoices):
|
|
||||||
HARDDRIVE = "HardDrive"
|
|
||||||
SOLIDSTATEDRIVE = "SolidStateDrive"
|
|
||||||
|
|
||||||
component = models.OneToOneField(Component, models.CASCADE)
|
|
||||||
size = models.IntegerField(blank=True, null=True)
|
size = models.IntegerField(blank=True, null=True)
|
||||||
interface = models.CharField(max_length=STR_SM_SIZE, choices=Interface)
|
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):
|
class Motherboard(models.Model):
|
||||||
|
|
|
@ -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 %}
|
|
@ -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 %}
|
|
@ -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 %}
|
|
@ -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('api/', include('snapshot.urls')),
|
||||||
path("", include("login.urls")),
|
path("", include("login.urls")),
|
||||||
path("dashboard/", include("dashboard.urls")),
|
path("dashboard/", include("dashboard.urls")),
|
||||||
|
path("device/", include("device.urls")),
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in New Issue