resolv conflicts
This commit is contained in:
commit
88a0bdd44d
|
@ -89,6 +89,26 @@ MONITORS = ["ComputerMonitor", "Monitor", "TelevisionSet", "Projector"]
|
||||||
MOBILE = ["Mobile", "Tablet", "Smartphone", "Cellphone"]
|
MOBILE = ["Mobile", "Tablet", "Smartphone", "Cellphone"]
|
||||||
|
|
||||||
|
|
||||||
|
class AdvancedSearchForm(FlaskForm):
|
||||||
|
q = StringField('Search', [validators.length(min=1)])
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
dhids = [x.strip() for x in self.q.data.split(' ')]
|
||||||
|
if ',' in self.q.data:
|
||||||
|
dhids = [x.strip() for x in self.q.data.split(',')]
|
||||||
|
if ';' in self.q.data:
|
||||||
|
dhids = [x.strip() for x in self.q.data.split(';')]
|
||||||
|
|
||||||
|
self.devices = []
|
||||||
|
if dhids:
|
||||||
|
self.search(dhids)
|
||||||
|
|
||||||
|
def search(self, dhids):
|
||||||
|
self.devices = Device.query.filter(Device.devicehub_id.in_(dhids))
|
||||||
|
|
||||||
|
|
||||||
class FilterForm(FlaskForm):
|
class FilterForm(FlaskForm):
|
||||||
filter = SelectField(
|
filter = SelectField(
|
||||||
'', choices=DEVICES, default="All Computers", render_kw={'class': "form-select"}
|
'', choices=DEVICES, default="All Computers", render_kw={'class': "form-select"}
|
||||||
|
|
|
@ -13,6 +13,7 @@ from werkzeug.exceptions import NotFound
|
||||||
from ereuse_devicehub import messages
|
from ereuse_devicehub import messages
|
||||||
from ereuse_devicehub.db import db
|
from ereuse_devicehub.db import db
|
||||||
from ereuse_devicehub.inventory.forms import (
|
from ereuse_devicehub.inventory.forms import (
|
||||||
|
AdvancedSearchForm,
|
||||||
AllocateForm,
|
AllocateForm,
|
||||||
DataWipeForm,
|
DataWipeForm,
|
||||||
EditTransferForm,
|
EditTransferForm,
|
||||||
|
@ -101,6 +102,19 @@ class DeviceListView(DeviceListMixin):
|
||||||
return flask.render_template(self.template_name, **self.context)
|
return flask.render_template(self.template_name, **self.context)
|
||||||
|
|
||||||
|
|
||||||
|
class AdvancedSearchView(DeviceListMixin):
|
||||||
|
methods = ['GET', 'POST']
|
||||||
|
template_name = 'inventory/search.html'
|
||||||
|
title = "Advanced Search"
|
||||||
|
|
||||||
|
def dispatch_request(self):
|
||||||
|
query = request.args.get('q', '')
|
||||||
|
self.get_context(None)
|
||||||
|
form = AdvancedSearchForm(q=query)
|
||||||
|
self.context.update({'devices': form.devices, 'advanced_form': form})
|
||||||
|
return flask.render_template(self.template_name, **self.context)
|
||||||
|
|
||||||
|
|
||||||
class DeviceDetailView(GenericMixin):
|
class DeviceDetailView(GenericMixin):
|
||||||
decorators = [login_required]
|
decorators = [login_required]
|
||||||
template_name = 'inventory/device_detail.html'
|
template_name = 'inventory/device_detail.html'
|
||||||
|
@ -630,6 +644,9 @@ devices.add_url_rule(
|
||||||
view_func=NewTradeDocumentView.as_view('trade_document_add'),
|
view_func=NewTradeDocumentView.as_view('trade_document_add'),
|
||||||
)
|
)
|
||||||
devices.add_url_rule('/device/', view_func=DeviceListView.as_view('devicelist'))
|
devices.add_url_rule('/device/', view_func=DeviceListView.as_view('devicelist'))
|
||||||
|
devices.add_url_rule(
|
||||||
|
'/search/', view_func=AdvancedSearchView.as_view('advanced_search')
|
||||||
|
)
|
||||||
devices.add_url_rule(
|
devices.add_url_rule(
|
||||||
'/device/<string:id>/', view_func=DeviceDetailView.as_view('device_details')
|
'/device/<string:id>/', view_func=DeviceDetailView.as_view('device_details')
|
||||||
)
|
)
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
min-width: max-content;
|
min-width: max-content;
|
||||||
max-height: 380px;
|
max-height: 330px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -348,10 +348,12 @@ class lotsSearcher {
|
||||||
const lots = this.getListLots();
|
const lots = this.getListLots();
|
||||||
|
|
||||||
for (let i = 0; i < lots.length; i++) {
|
for (let i = 0; i < lots.length; i++) {
|
||||||
|
const lot = lots[i];
|
||||||
|
|
||||||
if (lot.innerText.toLowerCase().includes(inputSearch.toLowerCase())) {
|
if (lot.innerText.toLowerCase().includes(inputSearch.toLowerCase())) {
|
||||||
lot.parentElement.style.display = "";
|
lot.style.display = "";
|
||||||
} else {
|
} else {
|
||||||
lot.parentElement.style.display = "none";
|
lot.style.display = "none";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -363,7 +365,7 @@ _defineProperty(lotsSearcher, "lots", []);
|
||||||
_defineProperty(lotsSearcher, "lotsSearchElement", null);
|
_defineProperty(lotsSearcher, "lotsSearchElement", null);
|
||||||
|
|
||||||
_defineProperty(lotsSearcher, "getListLots", () => {
|
_defineProperty(lotsSearcher, "getListLots", () => {
|
||||||
let lotsList = document.getElementById("LotsSelector");
|
const lotsList = document.getElementById("LotsSelector");
|
||||||
|
|
||||||
if (lotsList) {
|
if (lotsList) {
|
||||||
// Apply filter to get only labels
|
// Apply filter to get only labels
|
||||||
|
|
|
@ -345,10 +345,11 @@ class lotsSearcher {
|
||||||
static doSearch(inputSearch) {
|
static doSearch(inputSearch) {
|
||||||
const lots = this.getListLots();
|
const lots = this.getListLots();
|
||||||
for (let i = 0; i < lots.length; i++) {
|
for (let i = 0; i < lots.length; i++) {
|
||||||
|
const lot = lots[i]
|
||||||
if (lot.innerText.toLowerCase().includes(inputSearch.toLowerCase())) {
|
if (lot.innerText.toLowerCase().includes(inputSearch.toLowerCase())) {
|
||||||
lot.parentElement.style.display = "";
|
lot.style.display = "";
|
||||||
} else {
|
} else {
|
||||||
lot.parentElement.style.display = "none";
|
lot.style.display = "none";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,11 @@
|
||||||
style="float: right;">DHID</span></li>
|
style="float: right;">DHID</span></li>
|
||||||
<li class="dropdown-item"><i class="bi bi-folder2"></i> lots <span class="badge bg-secondary"
|
<li class="dropdown-item"><i class="bi bi-folder2"></i> lots <span class="badge bg-secondary"
|
||||||
style="float: right;">Name</span></li>
|
style="float: right;">Name</span></li>
|
||||||
|
<li class="dropdown-item">
|
||||||
|
<small class="text-muted">
|
||||||
|
<a href="{{ url_for('inventory.advanced_search')}}">Advanced Search</a>
|
||||||
|
</small>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</form>
|
</form>
|
||||||
</div><!-- End Search Bar -->
|
</div><!-- End Search Bar -->
|
||||||
|
|
|
@ -0,0 +1,412 @@
|
||||||
|
{% extends "ereuse_devicehub/base_site.html" %}
|
||||||
|
{% block main %}
|
||||||
|
|
||||||
|
<div class="pagetitle">
|
||||||
|
<h1>Inventory</h1>
|
||||||
|
<nav>
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li class="breadcrumb-item"><a href="{{ url_for('inventory.devicelist')}}">Inventory</a></li>
|
||||||
|
<li class="breadcrumb-item active">Advanced Search</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
</div><!-- End Page Title -->
|
||||||
|
|
||||||
|
<section class="section profile">
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<div class="col-xl-12">
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="tab-content pt-2">
|
||||||
|
<div class="flex mt-4 mb-4">
|
||||||
|
<form method="get" class="ms-4">
|
||||||
|
{% for f in advanced_form %}
|
||||||
|
{{ f }}
|
||||||
|
{% endfor %}
|
||||||
|
<input type="submit" class="ms-2 btn btn-primary" value="Search" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% if devices %}
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body pt-3" style="min-height: 650px;">
|
||||||
|
<!-- Bordered Tabs -->
|
||||||
|
<div class="tab-content pt-1">
|
||||||
|
<div id="devices-list" class="tab-pane fade devices-list active show">
|
||||||
|
<label class="btn btn-primary " for="SelectAllBTN"><input type="checkbox" id="SelectAllBTN" autocomplete="off"></label>
|
||||||
|
<div class="btn-group dropdown ml-1">
|
||||||
|
<button id="btnLots" type="button" onclick="processSelectedDevices()" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
<i class="bi bi-folder2"></i>
|
||||||
|
Lots
|
||||||
|
<span class="caret"></span>
|
||||||
|
</button>
|
||||||
|
<span class="d-none" id="activeTradeModal" data-bs-toggle="modal" data-bs-target="#tradeLotModal"></span>
|
||||||
|
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="btnLots" id="dropDownLotsSelector">
|
||||||
|
<div class="row w-100">
|
||||||
|
<div class="input-group mb-3 mx-2">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text" id="basic-addon1"><i class="bi bi-search"></i></span>
|
||||||
|
</div>
|
||||||
|
<input type="text" class="form-control" id="lots-search" placeholder="search" aria-label="search" aria-describedby="basic-addon1">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h6 class="dropdown-header">Select lots where to store the selected devices</h6>
|
||||||
|
<ul class="mx-3" id="LotsSelector"></ul>
|
||||||
|
<li><hr /></li>
|
||||||
|
<li>
|
||||||
|
<a href="#" class="dropdown-item" id="ApplyDeviceLots">
|
||||||
|
<i class="bi bi-check"></i>
|
||||||
|
Apply
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="btn-group dropdown m-1" uib-dropdown="">
|
||||||
|
<button id="btnActions" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
<i class="bi bi-plus"></i>
|
||||||
|
New Actions
|
||||||
|
</button>
|
||||||
|
<span class="d-none" id="activeActionModal" data-bs-toggle="modal" data-bs-target="#actionModal"></span>
|
||||||
|
<span class="d-none" id="activeAllocateModal" data-bs-toggle="modal" data-bs-target="#allocateModal"></span>
|
||||||
|
<span class="d-none" id="activeDatawipeModal" data-bs-toggle="modal" data-bs-target="#datawipeModal"></span>
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="btnActions">
|
||||||
|
<li>
|
||||||
|
Status actions
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:newAction('Recycling')" class="dropdown-item">
|
||||||
|
<i class="bi bi-recycle"></i>
|
||||||
|
Recycling
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:newAction('Use')" class="dropdown-item">
|
||||||
|
<i class="bi bi-play-circle-fill"></i>
|
||||||
|
Use
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:newAction('Refurbish')" class="dropdown-item">
|
||||||
|
<i class="bi bi-tools"></i>
|
||||||
|
Refurbish
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:newAction('Management')" class="dropdown-item">
|
||||||
|
<i class="bi bi-mastodon"></i>
|
||||||
|
Management
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Allocation
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:newAllocate('Allocate')" class="dropdown-item">
|
||||||
|
<i class="bi bi-house-fill"></i>
|
||||||
|
Allocate
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:newAllocate('Deallocate')" class="dropdown-item">
|
||||||
|
<i class="bi bi-house"></i>
|
||||||
|
Deallocate
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Physical actions
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:newAction('ToPrepare')" class="dropdown-item">
|
||||||
|
<i class="bi bi-tools"></i>
|
||||||
|
ToPrepare
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:newAction('Prepare')" class="dropdown-item">
|
||||||
|
<i class="bi bi-egg"></i>
|
||||||
|
Prepare
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:newDataWipe('DataWipe')" class="dropdown-item">
|
||||||
|
<i class="bi bi-eraser-fill"></i>
|
||||||
|
DataWipe
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:newAction('ToRepair')" class="dropdown-item">
|
||||||
|
<i class="bi bi-screwdriver"></i>
|
||||||
|
ToRepair
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:newAction('Ready')" class="dropdown-item">
|
||||||
|
<i class="bi bi-check2-all"></i>
|
||||||
|
Ready
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-group dropdown m-1" uib-dropdown="">
|
||||||
|
<button id="btnExport" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
<i class="bi bi-reply"></i>
|
||||||
|
Exports
|
||||||
|
</button>
|
||||||
|
<span class="d-none" id="exportAlertModal" data-bs-toggle="modal" data-bs-target="#exportErrorModal"></span>
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="btnExport">
|
||||||
|
<li>
|
||||||
|
<a href="javascript:export_file('devices')" class="dropdown-item">
|
||||||
|
<i class="bi bi-file-spreadsheet"></i>
|
||||||
|
Devices Spreadsheet
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:export_file('metrics')" class="dropdown-item">
|
||||||
|
<i class="bi bi-file-spreadsheet"></i>
|
||||||
|
Metrics Spreadsheet
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:export_file('certificates')" class="dropdown-item">
|
||||||
|
<i class="bi bi-eraser-fill"></i>
|
||||||
|
Erasure Certificate
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-group dropdown m-1" uib-dropdown="">
|
||||||
|
<button id="btnUniqueID" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
<i class="bi bi-tag"></i>
|
||||||
|
Unique Identifiers (Tags)
|
||||||
|
</button>
|
||||||
|
<span class="d-none" id="unlinkTagAlertModal" data-bs-toggle="modal" data-bs-target="#unlinkTagErrorModal"></span>
|
||||||
|
<span class="d-none" id="addTagAlertModal" data-bs-toggle="modal" data-bs-target="#addingTagModal"></span>
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="btnUniqueID">
|
||||||
|
<li>
|
||||||
|
<a href="javascript:addTag()" class="dropdown-item">
|
||||||
|
<i class="bi bi-plus"></i>
|
||||||
|
Add Unique Identifier to selected Device
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:removeTag()" class="dropdown-item">
|
||||||
|
<i class="bi bi-x"></i>
|
||||||
|
Remove Unique Identifier from selected Device
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item" href="{{ url_for('labels.label_list')}}">
|
||||||
|
<i class="bi bi-tools"></i>
|
||||||
|
Unique Identifier Management
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-group dropdown m-1" uib-dropdown="">
|
||||||
|
<button id="btnTags" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
<i class="bi bi-tag"></i>
|
||||||
|
Labels
|
||||||
|
</button>
|
||||||
|
<span class="d-none" id="unlinkTagAlertModal" data-bs-toggle="modal" data-bs-target="#unlinkTagErrorModal"></span>
|
||||||
|
<span class="d-none" id="addTagAlertModal" data-bs-toggle="modal" data-bs-target="#addingTagModal"></span>
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="btnTags">
|
||||||
|
<li>
|
||||||
|
<form id="print_labels" method="post" action="{{ url_for('labels.print_labels') }}">
|
||||||
|
{% for f in form_print_labels %}
|
||||||
|
{{ f }}
|
||||||
|
{% endfor %}
|
||||||
|
<a href="javascript:$('#print_labels').submit()" class="dropdown-item">
|
||||||
|
<i class="bi bi-printer"></i>
|
||||||
|
Print labels
|
||||||
|
</a>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-group dropdown m-1" uib-dropdown="">
|
||||||
|
<button id="btnSnapshot" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
<i class="bi bi-laptop"></i>
|
||||||
|
New Device
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="btnSnapshot">
|
||||||
|
<li>
|
||||||
|
{% if lot %}
|
||||||
|
<a href="{{ url_for('inventory.lot_upload_snapshot', lot_id=lot.id) }}" class="dropdown-item">
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ url_for('inventory.upload_snapshot') }}" class="dropdown-item">
|
||||||
|
{% endif %}
|
||||||
|
<i class="bi bi-upload"></i>
|
||||||
|
Upload a new Snapshot
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
{% if lot %}
|
||||||
|
<a href="{{ url_for('inventory.lot_device_add', lot_id=lot.id) }}" class="dropdown-item">
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ url_for('inventory.device_add') }}" class="dropdown-item">
|
||||||
|
{% endif %}
|
||||||
|
<i class="bi bi-plus"></i>
|
||||||
|
Create a new Device
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if lot and not lot.is_temporary %}
|
||||||
|
<div class="btn-group dropdown ml-1" uib-dropdown="">
|
||||||
|
<button id="btnSnapshot" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
<i class="bi bi-book"></i>
|
||||||
|
Documents
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="btnSnapshot">
|
||||||
|
<li>
|
||||||
|
<a href="{{ url_for('inventory.trade_document_add', lot_id=lot.id)}}" class="dropdown-item">
|
||||||
|
<i class="bi bi-plus"></i>
|
||||||
|
Add new document
|
||||||
|
<span class="caret"></span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div id="select-devices-info" class="alert alert-info mb-0 mt-3 d-none" role="alert">
|
||||||
|
If this text is showing is because there are an error
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tab-content pt-2">
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Select</th>
|
||||||
|
<th scope="col">Title</th>
|
||||||
|
<th scope="col">DHID</th>
|
||||||
|
<th scope="col">Unique Identifiers</th>
|
||||||
|
<th scope="col">Lifecycle Status</th>
|
||||||
|
<th scope="col">Allocated Status</th>
|
||||||
|
<th scope="col">Physical Status</th>
|
||||||
|
<th scope="col" data-type="date" data-format="YYYY-MM-DD">Updated in</th>
|
||||||
|
<th scope="col" data-type="date" data-format="YYYY-MM-DD hh:mm:ss">Registered in</th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for dev in devices %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" class="deviceSelect" data="{{ dev.id }}"
|
||||||
|
data-device-type="{{ dev.type }}" data-device-manufacturer="{{ dev.manufacturer }}"
|
||||||
|
data-device-dhid="{{ dev.devicehub_id }}" data-device-vname="{{ dev.verbose_name }}"
|
||||||
|
{% if form_new_allocate.type.data and dev.id in list_devices %}
|
||||||
|
checked="checked"
|
||||||
|
{% endif %}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="{{ url_for('inventory.device_details', id=dev.devicehub_id)}}">
|
||||||
|
{% if dev.get_type_logo() %}
|
||||||
|
<i class="{{ dev.get_type_logo() }}" title="{{ dev.type }}"></i>
|
||||||
|
{% endif %}
|
||||||
|
{{ dev.verbose_name }}
|
||||||
|
</a>
|
||||||
|
{% if dev.lots | length > 0 %}
|
||||||
|
<h6 class="d-inline">
|
||||||
|
{% for lot in dev.lots %}
|
||||||
|
<span class="badge rounded-pill bg-light text-dark">{{ lot.name }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</h6>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="{{ url_for('inventory.device_details', id=dev.devicehub_id)}}">
|
||||||
|
{{ dev.devicehub_id }}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% for t in dev.tags | sort(attribute="id") %}
|
||||||
|
<a href="{{ url_for('labels.label_details', id=t.id)}}">{{ t.id }}</a>
|
||||||
|
{% if not loop.last %},{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
<td>{% if dev.status %}{{ dev.status.type }}{% endif %}</td>
|
||||||
|
<td>{% if dev.allocated_status %}{{ dev.allocated_status.type }}{% endif %}</td>
|
||||||
|
<td>{% if dev.physical_status %}{{ dev.physical_status.type }}{% endif %}</td>
|
||||||
|
<td>{{ dev.updated.strftime('%Y-%m-%d %H:%M:%S')}}</td>
|
||||||
|
<td>{{ dev.created.strftime('%Y-%m-%d %H:%M:%S')}}</td>
|
||||||
|
<td>
|
||||||
|
<a href="{{ dev.public_link }}" target="_blank">
|
||||||
|
<i class="bi bi-box-arrow-up-right"></i>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% if lot and not lot.is_temporary %}
|
||||||
|
<div id="trade-documents-list" class="tab-pane fade trade-documents-list">
|
||||||
|
<h5 class="card-title">Documents</h5>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">File</th>
|
||||||
|
<th scope="col" data-type="date" data-format="DD-MM-YYYY">Uploaded on</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for doc in lot.trade.documents %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{% if doc.url %}
|
||||||
|
<a href="{{ doc.url.to_text() }}" target="_blank">{{ doc.file_name}}</a>
|
||||||
|
{% else %}
|
||||||
|
{{ doc.file_name}}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ doc.created.strftime('%H:%M %d-%m-%Y')}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div><!-- End Bordered Tabs -->
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="NotificationsContainer" style="position: absolute; bottom: 0; right: 0; margin: 10px; margin-top: 70px; width: calc(100% - 310px);"></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% include "inventory/addDevicestag.html" %}
|
||||||
|
{% include "inventory/lot_delete_modal.html" %}
|
||||||
|
{% include "inventory/actions.html" %}
|
||||||
|
{% include "inventory/allocate.html" %}
|
||||||
|
{% include "inventory/data_wipe.html" %}
|
||||||
|
{% include "inventory/trade.html" %}
|
||||||
|
{% include "inventory/alert_export_error.html" %}
|
||||||
|
{% include "inventory/alert_unlink_tag_error.html" %}
|
||||||
|
{% include "inventory/alert_lots_changes.html" %}
|
||||||
|
|
||||||
|
<!-- Custom Code -->
|
||||||
|
<script>
|
||||||
|
let table = new simpleDatatables.DataTable("table", {
|
||||||
|
perPage: 20
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<script src="{{ url_for('static', filename='js/main_inventory.build.js') }}"></script>
|
||||||
|
{% endblock main %}
|
|
@ -42,6 +42,6 @@ sortedcontainers==2.1.0
|
||||||
tqdm==4.32.2
|
tqdm==4.32.2
|
||||||
python-decouple==3.3
|
python-decouple==3.3
|
||||||
python-dotenv==0.14.0
|
python-dotenv==0.14.0
|
||||||
pyjwt==2.0.0a1
|
pyjwt==2.4.0
|
||||||
pint==0.9
|
pint==0.9
|
||||||
py-dmidecode==0.1.0
|
py-dmidecode==0.1.0
|
||||||
|
|
|
@ -43,6 +43,7 @@ def test_api_docs(client: Client):
|
||||||
'/documents/erasures/',
|
'/documents/erasures/',
|
||||||
'/documents/internalstats/',
|
'/documents/internalstats/',
|
||||||
'/documents/lots/',
|
'/documents/lots/',
|
||||||
|
'/inventory/search/',
|
||||||
'/documents/stamps/',
|
'/documents/stamps/',
|
||||||
'/documents/static/{filename}',
|
'/documents/static/{filename}',
|
||||||
'/documents/stock/',
|
'/documents/stock/',
|
||||||
|
|
Reference in New Issue