mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
Convert the inventory page to Laravel (#15004)
* Convert the inventory page to Laravel Fix several XSS issues (hopefully no new ones snuck in) Small improvement to the SelectController to allow filtering by filterFields() * style fixes * Fix lint issues * Fix part device filter
This commit is contained in:
50
app/Http/Controllers/InventoryController.php
Normal file
50
app/Http/Controllers/InventoryController.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\EntPhysical;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class InventoryController extends Controller
|
||||
{
|
||||
public function __invoke(Request $request): View
|
||||
{
|
||||
$this->validate($request, [
|
||||
'device' => 'nullable|int',
|
||||
'descr' => 'nullable|string',
|
||||
'model' => 'nullable|string',
|
||||
'serial' => 'nullable|string',
|
||||
]);
|
||||
|
||||
$device = \App\Models\Device::hasAccess($request->user())
|
||||
->select(['device_id', 'hostname', 'ip', 'sysName', 'display'])
|
||||
->firstWhere('device_id', $request->get('device'));
|
||||
|
||||
$model_filter = ['field' => 'model'];
|
||||
$device_selected = '';
|
||||
if ($device) {
|
||||
$device_selected = ['id' => $device->device_id, 'text' => $device->displayName()];
|
||||
$model_filter['device_id'] = $device->device_id;
|
||||
}
|
||||
|
||||
return view('inventory', [
|
||||
'device_selected' => $device_selected,
|
||||
'filter' => [
|
||||
'device' => $device?->device_id,
|
||||
'descr' => $request->get('descr'),
|
||||
'model' => $request->get('model'),
|
||||
'serial' => $request->get('serial'),
|
||||
],
|
||||
'model_filter' => $model_filter,
|
||||
'show_purge' => EntPhysical::whereDoesntHave('device')->exists(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function purge()
|
||||
{
|
||||
EntPhysical::whereDoesntHave('device')->delete();
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
}
|
70
app/Http/Controllers/Select/InventoryController.php
Normal file
70
app/Http/Controllers/Select/InventoryController.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
/**
|
||||
* EntPhysicalController.php
|
||||
*
|
||||
* -Description-
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @link https://www.librenms.org
|
||||
*
|
||||
* @copyright 2023 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Select;
|
||||
|
||||
use App\Models\EntPhysical;
|
||||
|
||||
class InventoryController extends SelectController
|
||||
{
|
||||
protected function rules()
|
||||
{
|
||||
return [
|
||||
'field' => 'required|in:name,model,descr,class',
|
||||
'device' => 'nullable|int',
|
||||
];
|
||||
}
|
||||
|
||||
protected function filterFields($request)
|
||||
{
|
||||
return ['device_id'];
|
||||
}
|
||||
|
||||
protected function searchFields($request)
|
||||
{
|
||||
return [$this->fieldToColumn($request->get('field'))];
|
||||
}
|
||||
|
||||
protected function baseQuery($request)
|
||||
{
|
||||
$column = $this->fieldToColumn($request->get('field'));
|
||||
|
||||
return EntPhysical::hasAccess($request->user())
|
||||
->select($column)
|
||||
->orderBy($column)
|
||||
->distinct();
|
||||
}
|
||||
|
||||
private function fieldToColumn(string $field): string
|
||||
{
|
||||
return match ($field) {
|
||||
'name' => 'entPhysicalName',
|
||||
'model' => 'entPhysicalModelName',
|
||||
'descr' => 'entPhysicalDescr',
|
||||
'class' => 'entPhysicalClass',
|
||||
default => 'entPhysicalName',
|
||||
};
|
||||
}
|
||||
}
|
@@ -42,6 +42,19 @@ class PortFieldController extends SelectController
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines fields that can be used as filters
|
||||
*
|
||||
* @param $request
|
||||
* @return string[]
|
||||
*/
|
||||
protected function filterFields($request)
|
||||
{
|
||||
return [
|
||||
'device_id' => 'device',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines search fields will be searched in order
|
||||
*
|
||||
@@ -61,14 +74,7 @@ class PortFieldController extends SelectController
|
||||
*/
|
||||
protected function baseQuery($request)
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $query */
|
||||
$query = Port::hasAccess($request->user())
|
||||
return Port::hasAccess($request->user())
|
||||
->select($request->get('field'))->distinct();
|
||||
|
||||
if ($device_id = $request->get('device')) {
|
||||
$query->where('ports.device_id', $device_id);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
|
@@ -57,7 +57,8 @@ abstract class SelectController extends PaginatedAjaxController
|
||||
$query = $this->baseQuery($request)->when($request->has('id'), function ($query) {
|
||||
return $query->whereKey(request('id'));
|
||||
});
|
||||
$query = $this->search($request->get('term'), $query, $this->searchFields($request));
|
||||
$this->filter($request, $query, $this->filterFields($request));
|
||||
$this->search($request->get('term'), $query, $this->searchFields($request));
|
||||
$this->sort($request, $query);
|
||||
$paginator = $query->simplePaginate($limit);
|
||||
|
||||
|
96
app/Http/Controllers/Table/InventoryController.php
Normal file
96
app/Http/Controllers/Table/InventoryController.php
Normal file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
/**
|
||||
* InventoryController.php
|
||||
*
|
||||
* -Description-
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @link https://www.librenms.org
|
||||
*
|
||||
* @copyright 2023 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Table;
|
||||
|
||||
use App\Models\EntPhysical;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
use LibreNMS\Util\Url;
|
||||
|
||||
class InventoryController extends TableController
|
||||
{
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'device' => 'nullable|int',
|
||||
'descr' => 'nullable|string',
|
||||
'model'=> 'nullable|string',
|
||||
'serial' => 'nullable|string',
|
||||
];
|
||||
}
|
||||
|
||||
protected function filterFields($request)
|
||||
{
|
||||
return [
|
||||
'device_id' => 'device',
|
||||
];
|
||||
}
|
||||
|
||||
protected function searchFields($request)
|
||||
{
|
||||
return ['entPhysicalDescr', 'entPhysicalModelName', 'entPhysicalSerialNum'];
|
||||
}
|
||||
|
||||
protected function sortFields($request)
|
||||
{
|
||||
return [
|
||||
'device' => 'device_id',
|
||||
'name' => 'entPhysicalName',
|
||||
'descr' => 'entPhysicalDescr',
|
||||
'model' => 'entPhysicalModelName',
|
||||
'serial' => 'entPhysicalSerialNum',
|
||||
];
|
||||
}
|
||||
|
||||
protected function baseQuery($request)
|
||||
{
|
||||
$query = EntPhysical::hasAccess($request->user())
|
||||
->with('device')
|
||||
->select(['entPhysical_id', 'device_id', 'entPhysicalDescr', 'entPhysicalName', 'entPhysicalModelName', 'entPhysicalSerialNum']);
|
||||
|
||||
// apply specific field filters
|
||||
$this->search($request->get('descr'), $query, ['entPhysicalDescr']);
|
||||
$this->search($request->get('model'), $query, ['entPhysicalModelName']);
|
||||
$this->search($request->get('serial'), $query, ['entPhysicalSerialNum']);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EntPhysical $entPhysical
|
||||
* @return array|Model|Collection
|
||||
*/
|
||||
public function formatItem($entPhysical)
|
||||
{
|
||||
return [
|
||||
'device' => Url::deviceLink($entPhysical->device),
|
||||
'descr' => htmlspecialchars($entPhysical->entPhysicalDescr),
|
||||
'name' => htmlspecialchars($entPhysical->entPhysicalName),
|
||||
'model' => htmlspecialchars($entPhysical->entPhysicalModelName),
|
||||
'serial' => htmlspecialchars($entPhysical->entPhysicalSerialNum),
|
||||
];
|
||||
}
|
||||
}
|
@@ -61,8 +61,8 @@ abstract class TableController extends PaginatedAjaxController
|
||||
/** @var Builder $query */
|
||||
$query = $this->baseQuery($request);
|
||||
|
||||
$this->search($request->get('searchPhrase'), $query, $this->searchFields($request));
|
||||
$this->filter($request, $query, $this->filterFields($request));
|
||||
$this->search($request->get('searchPhrase'), $query, $this->searchFields($request));
|
||||
$this->sort($request, $query);
|
||||
|
||||
$limit = $request->get('rowCount', 25);
|
||||
|
File diff suppressed because one or more lines are too long
@@ -2,15 +2,15 @@
|
||||
"/js/app.js": "/js/app.js?id=5ddec7f7302f146a8dcc",
|
||||
"/js/manifest.js": "/js/manifest.js?id=2951ae529be231f05a93",
|
||||
"/css/vendor.css": "/css/vendor.css?id=2568831af31dbfc3128a",
|
||||
"/css/app.css": "/css/app.css?id=bd093a6a2e2682bb59ef",
|
||||
"/css/app.css": "/css/app.css?id=1cd88608bf4eaee000d8",
|
||||
"/js/vendor.js": "/js/vendor.js?id=c5fd3d75a63757080dbb",
|
||||
"/js/lang/de.js": "/js/lang/de.js?id=613b5ca9cd06ca15e384",
|
||||
"/js/lang/en.js": "/js/lang/en.js?id=efa23897934359283288",
|
||||
"/js/lang/fr.js": "/js/lang/fr.js?id=4540d71a19d8ca7c824b",
|
||||
"/js/lang/it.js": "/js/lang/it.js?id=71c68fae57a4a3647e43",
|
||||
"/js/lang/de.js": "/js/lang/de.js?id=d74df23e729c5dabfee8",
|
||||
"/js/lang/en.js": "/js/lang/en.js?id=20e52084af3a0a8f4724",
|
||||
"/js/lang/fr.js": "/js/lang/fr.js?id=22902d30358443ef2877",
|
||||
"/js/lang/it.js": "/js/lang/it.js?id=6220e138068a7e58387f",
|
||||
"/js/lang/ru.js": "/js/lang/ru.js?id=f6b7c078755312a0907c",
|
||||
"/js/lang/sr.js": "/js/lang/sr.js?id=388e38b41f63e3517506",
|
||||
"/js/lang/uk.js": "/js/lang/uk.js?id=72f81fcbf77df09d0c82",
|
||||
"/js/lang/zh-CN.js": "/js/lang/zh-CN.js?id=4e081fbac70d969894bf",
|
||||
"/js/lang/zh-TW.js": "/js/lang/zh-TW.js?id=ed26425647721a42ee9d"
|
||||
"/js/lang/uk.js": "/js/lang/uk.js?id=fdfb4cfa77a3340e50f8",
|
||||
"/js/lang/zh-CN.js": "/js/lang/zh-CN.js?id=cc4309e63a32a671f107",
|
||||
"/js/lang/zh-TW.js": "/js/lang/zh-TW.js?id=2248687ad44f27299377"
|
||||
}
|
||||
|
@@ -1,100 +0,0 @@
|
||||
<?php
|
||||
|
||||
$pagetitle[] = 'Inventory';
|
||||
|
||||
?>
|
||||
|
||||
<div class="panel panel-default panel-condensed">
|
||||
<div class="panel-heading">
|
||||
<strong>Inventory</strong>
|
||||
</div>
|
||||
<table id="inventory" class="table table-hover table-condensed table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="hostname" data-order="asc">Hostname</th>
|
||||
<th data-column-id="description">Description</th>
|
||||
<th data-column-id="name">Name</th>
|
||||
<th data-column-id="model">Part No</th>
|
||||
<th data-column-id="serial">Serial No</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
var grid = $("#inventory").bootgrid({
|
||||
ajax: true,
|
||||
rowCount: [50, 100, 250, -1],
|
||||
templates: {
|
||||
header: "<div id=\"{{ctx.id}}\" class=\"{{css.header}}\"><div class=\"row\">"+
|
||||
"<div class=\"col-sm-9 actionBar\"><span class=\"pull-left\"><form method=\"post\" action=\"\" class=\"form-inline\" role=\"form\">"+
|
||||
"<?php echo addslashes(csrf_field()) ?>"+
|
||||
"<div class=\"form-group\">"+
|
||||
"<input type=\"text\" name=\"string\" id=\"string\" value=\"<?php echo htmlspecialchars($_POST['string']); ?>\" placeholder=\"Description\" class=\"form-control input-sm\" />"+
|
||||
"</div>"+
|
||||
"<div class=\"form-group\">"+
|
||||
"<strong> Part No </strong>"+
|
||||
"<select name=\"part\" id=\"part\" class=\"form-control input-sm\">"+
|
||||
"<option value=\"\">All Parts</option>"+
|
||||
<?php
|
||||
foreach (dbFetchRows('SELECT `entPhysicalModelName` FROM `entPhysical` GROUP BY `entPhysicalModelName` ORDER BY `entPhysicalModelName`') as $data) {
|
||||
echo '"<option value=\"' . $data['entPhysicalModelName'] . '\""+';
|
||||
if ($data['entPhysicalModelName'] == $_POST['part']) {
|
||||
echo '" selected"+';
|
||||
}
|
||||
|
||||
echo '">' . $data['entPhysicalModelName'] . '</option>"+';
|
||||
}
|
||||
?>
|
||||
"</select>"+
|
||||
"</div>"+
|
||||
"<div class=\"form-group\">"+
|
||||
"<input type=\"text\" name=\"serial\" id=\"serial\" value=\"<?php echo htmlspecialchars($_POST['serial']); ?>\" placeholder=\"Serial\" class=\"form-control input-sm\"/>"+
|
||||
"</div>"+
|
||||
"<div class=\"form-group\">"+
|
||||
"<strong> Device </strong>"+
|
||||
"<select name=\"device\" id=\"device\" class=\"form-control input-sm\">"+
|
||||
"<option value=\"\">All Devices</option>"+
|
||||
<?php
|
||||
foreach (dbFetchRows('SELECT * FROM `devices` ORDER BY `hostname`') as $data) {
|
||||
if (device_permitted($data['device_id'])) {
|
||||
echo '"<option value=\"' . $data['device_id'] . '\""+';
|
||||
if ($data['device_id'] == $_POST['device']) {
|
||||
echo '" selected"+';
|
||||
}
|
||||
|
||||
echo '">' . format_hostname($data) . '</option>"+';
|
||||
}
|
||||
}
|
||||
?>
|
||||
"</select>"+
|
||||
"</div>"+
|
||||
"<div class=\"form-group\">"+
|
||||
"<input type=\"text\" size=24 name=\"device_string\" id=\"device_string\" value=\""+
|
||||
<?php
|
||||
if ($_POST['device_string']) {
|
||||
echo htmlspecialchars($_POST['device_string']);
|
||||
}
|
||||
?>
|
||||
"\" placeholder=\"Description\" class=\"form-control input-sm\"/>"+
|
||||
"</div>"+
|
||||
"<button type=\"submit\" class=\"btn btn-default input-sm\">Search</button>"+
|
||||
"</form></span></div>"+
|
||||
"<div class=\"col-sm-3 actionBar\"><p class=\"{{css.actions}}\"></p></div></div></div>"
|
||||
},
|
||||
post: function ()
|
||||
{
|
||||
return {
|
||||
id: "inventory",
|
||||
device: '<?php echo htmlspecialchars($_POST['device']); ?>',
|
||||
string: '<?php echo htmlspecialchars($_POST['string']); ?>',
|
||||
device_string: '<?php echo htmlspecialchars($_POST['device_string']); ?>',
|
||||
part: '<?php echo htmlspecialchars($_POST['part']); ?>',
|
||||
serial: '<?php echo htmlspecialchars($_POST['serial']); ?>'
|
||||
};
|
||||
},
|
||||
url: "ajax_table.php"
|
||||
});
|
||||
|
||||
</script>
|
@@ -1,86 +0,0 @@
|
||||
<?php
|
||||
|
||||
$where = '1';
|
||||
$param = [];
|
||||
|
||||
if (! Auth::user()->hasGlobalRead()) {
|
||||
$device_ids = Permissions::devicesForUser()->toArray() ?: [0];
|
||||
$where .= ' AND `D`.`device_id` IN ' . dbGenPlaceholders(count($device_ids));
|
||||
$param = array_merge($param, $device_ids);
|
||||
}
|
||||
|
||||
$sql = " FROM entPhysical AS E, devices AS D WHERE $where AND D.device_id = E.device_id";
|
||||
|
||||
if (isset($searchPhrase) && ! empty($searchPhrase)) {
|
||||
$sql .= ' AND (`D`.`hostname` LIKE ? OR `E`.`entPhysicalDescr` LIKE ? OR `E`.`entPhysicalModelName` LIKE ? OR `E`.`entPhysicalSerialNum` LIKE ?)';
|
||||
$param[] = "%$searchPhrase%";
|
||||
$param[] = "%$searchPhrase%";
|
||||
$param[] = "%$searchPhrase%";
|
||||
$param[] = "%$searchPhrase%";
|
||||
}
|
||||
|
||||
if (isset($vars['string']) && strlen($vars['string'])) {
|
||||
$sql .= ' AND E.entPhysicalDescr LIKE ?';
|
||||
$param[] = '%' . $vars['string'] . '%';
|
||||
}
|
||||
|
||||
if (isset($vars['device_string']) && strlen($vars['device_string'])) {
|
||||
$sql .= ' AND D.hostname LIKE ?';
|
||||
$param[] = '%' . $vars['device_string'] . '%';
|
||||
}
|
||||
|
||||
if (isset($vars['part']) && strlen($vars['part'])) {
|
||||
$sql .= ' AND E.entPhysicalModelName = ?';
|
||||
$param[] = $vars['part'];
|
||||
}
|
||||
|
||||
if (isset($vars['serial']) && strlen($vars['serial'])) {
|
||||
$sql .= ' AND E.entPhysicalSerialNum LIKE ?';
|
||||
$param[] = '%' . $vars['serial'] . '%';
|
||||
}
|
||||
|
||||
if (isset($vars['device']) && is_numeric($vars['device'])) {
|
||||
$sql .= ' AND D.device_id = ?';
|
||||
$param[] = $vars['device'];
|
||||
}
|
||||
|
||||
$count_sql = "SELECT COUNT(`entPhysical_id`) $sql";
|
||||
$total = dbFetchCell($count_sql, $param);
|
||||
if (empty($total)) {
|
||||
$total = 0;
|
||||
}
|
||||
|
||||
if (! isset($sort) || empty($sort)) {
|
||||
$sort = '`hostname` DESC';
|
||||
}
|
||||
|
||||
$sql .= " ORDER BY $sort";
|
||||
|
||||
if (isset($current)) {
|
||||
$limit_low = (($current * $rowCount) - $rowCount);
|
||||
$limit_high = $rowCount;
|
||||
}
|
||||
|
||||
if ($rowCount != -1) {
|
||||
$sql .= " LIMIT $limit_low,$limit_high";
|
||||
}
|
||||
|
||||
$sql = "SELECT `D`.`device_id` AS `device_id`, `D`.`os` AS `os`, `D`.`hostname` AS `hostname`, `D`.`sysName` AS `sysName`,`entPhysicalDescr` AS `description`, `entPhysicalName` AS `name`, `entPhysicalModelName` AS `model`, `entPhysicalSerialNum` AS `serial` $sql";
|
||||
|
||||
foreach (dbFetchRows($sql, $param) as $invent) {
|
||||
$response[] = [
|
||||
'hostname' => generate_device_link($invent),
|
||||
'description' => $invent['description'],
|
||||
'name' => $invent['name'],
|
||||
'model' => $invent['model'],
|
||||
'serial' => $invent['serial'],
|
||||
];
|
||||
}
|
||||
|
||||
$output = [
|
||||
'current' => $current,
|
||||
'rowCount' => $rowCount,
|
||||
'rows' => $response,
|
||||
'total' => $total,
|
||||
];
|
||||
echo json_encode($output, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
10
lang/en/inventory.php
Normal file
10
lang/en/inventory.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'purge' => 'Purge Non-Existent',
|
||||
'name' => 'Part Name',
|
||||
'model' => 'Part No',
|
||||
'serial' => 'Serial No',
|
||||
'part' => 'Part',
|
||||
'all_parts' => 'All Parts',
|
||||
];
|
86
resources/views/inventory.blade.php
Normal file
86
resources/views/inventory.blade.php
Normal file
@@ -0,0 +1,86 @@
|
||||
@extends('layouts.librenmsv1')
|
||||
|
||||
@section('title', __('Inventory'))
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid">
|
||||
<x-panel body-class="!tw-p-0">
|
||||
<x-slot name="heading">
|
||||
<h3 class="panel-title">@lang('Inventory')</h3>
|
||||
@if($show_purge)
|
||||
<div class="tw-float-right">
|
||||
<a href="{{ route('inventory.purge') }}"><i class="fa fa-trash"></i> @lang('inventory.purge')</a>
|
||||
</div>
|
||||
@endif
|
||||
</x-slot>
|
||||
|
||||
<table id="inventory" class="table table-hover table-condensed table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="device" data-order="asc">@lang('Device')</th>
|
||||
<th data-column-id="descr">@lang('Description')</th>
|
||||
<th data-column-id="name">@lang('inventory.name')</th>
|
||||
<th data-column-id="model">@lang('inventory.model')</th>
|
||||
<th data-column-id="serial">@lang('inventory.serial')</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</x-panel>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
var grid = $("#inventory").bootgrid({
|
||||
ajax: true,
|
||||
rowCount: [50, 100, 250, -1],
|
||||
templates: {
|
||||
header: "<div id=\"@{{ctx.id}}\" class=\"@{{css.header}} tw-flex tw-flex-wrap\">" +
|
||||
"<form method=\"post\" action=\"\" class=\"tw-flex tw-flex-wrap tw-items-center\" role=\"form\" id=\"inventory_filter\">" +
|
||||
"{!! addslashes(csrf_field()) !!}" +
|
||||
"<div class=\"tw-flex tw-items-baseline tw-mr-3 tw-mt-2\">" +
|
||||
"<span class=\"tw-mr-1\">@lang('inventory.part')</span>" +
|
||||
"<input type=\"text\" name=\"descr\" id=\"descr\" value=\"{{ $filter['descr'] }}\" placeholder=\"@lang('Description')\" class=\"form-control\" />" +
|
||||
"</div>" +
|
||||
"<div class=\"tw-flex tw-items-baseline tw-mr-3 tw-mt-2\">" +
|
||||
"<span class=\"tw-mr-1\">@lang('inventory.model')</span>" +
|
||||
"<select name=\"model\" id=\"model\" class=\"form-control\"></select>" +
|
||||
"</div>" +
|
||||
"<div class=\"tw-flex tw-items-baseline tw-mr-3 tw-mt-2\">" +
|
||||
"<input type=\"text\" name=\"serial\" id=\"serial\" value=\"{{ $filter['serial'] }}\" placeholder=\"@lang('inventory.serial')\" class=\"form-control\"/>" +
|
||||
"</div>" +
|
||||
"<div class=\"tw-flex tw-items-baseline tw-mr-3 tw-mt-2\">" +
|
||||
"<span class=\"tw-mr-1\">@lang('Device')</span>" +
|
||||
"<select name=\"device\" id=\"device\" class=\"form-control tw-ml-2\"></select>" +
|
||||
"</div>" +
|
||||
"<button type=\"submit\" class=\"btn btn-default tw-mr-2 tw-mt-2\">@lang('Search')</button>" +
|
||||
"</form>" +
|
||||
"<div class=\"actionBar tw-ml-auto tw-relative tw-mt-2\"><div class=\"@{{css.actions}}\"></div></div>" +
|
||||
"</div>"
|
||||
},
|
||||
post: function () {
|
||||
return @json($filter)
|
||||
},
|
||||
url: "{{ route('table.inventory') }}"
|
||||
});
|
||||
|
||||
<?php
|
||||
|
||||
?>
|
||||
|
||||
init_select2("#model", "inventory", @json($model_filter), @json($filter['model']), "@lang('inventory.all_parts')");
|
||||
init_select2("#device", "device", {}, @json($device_selected) , "@lang('All Devices')");
|
||||
</script>
|
||||
@endpush
|
||||
|
||||
@push('styles')
|
||||
<style>
|
||||
.actionBar > .actions {
|
||||
display: flex;
|
||||
}
|
||||
.actionBar > .actions > * {
|
||||
float: none;
|
||||
}
|
||||
</style>
|
||||
@endpush
|
||||
|
@@ -133,7 +133,7 @@
|
||||
aria-hidden="true"></i> {{ __('Graylog') }}</a></li>
|
||||
@endconfig
|
||||
|
||||
<li><a href="{{ url('inventory') }}"><i class="fa fa-cube fa-fw fa-lg"
|
||||
<li><a href="{{ route('inventory') }}"><i class="fa fa-cube fa-fw fa-lg"
|
||||
aria-hidden="true"></i> {{ __('Inventory') }}</a></li>
|
||||
<li><a href="{{ url('outages') }}"><i class="fa fa-bar-chart fa-fw fa-lg"
|
||||
aria-hidden="true"></i> {{ __('Outages') }}</a></li>
|
||||
@@ -762,7 +762,7 @@
|
||||
@endif
|
||||
|
||||
$(document).ready(function(){
|
||||
// Function to focus Global Search on Ctrl-F
|
||||
// Function to focus Global Search on Ctrl-F
|
||||
window.addEventListener("keydown",function (e) {
|
||||
if (e.keyCode === 114 || (e.ctrlKey && e.keyCode === 70)){
|
||||
if($('#gsearch').is(":focus")) {
|
||||
@@ -775,7 +775,7 @@
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
})
|
||||
</script>
|
||||
|
@@ -39,6 +39,8 @@ Route::middleware(['auth'])->group(function () {
|
||||
// pages
|
||||
Route::post('alert/{alert}/ack', [AlertController::class, 'ack'])->name('alert.ack');
|
||||
Route::resource('device-groups', 'DeviceGroupController');
|
||||
Route::any('inventory', \App\Http\Controllers\InventoryController::class)->name('inventory');
|
||||
Route::get('inventory/purge', [\App\Http\Controllers\InventoryController::class, 'purge'])->name('inventory.purge');
|
||||
Route::resource('port', 'PortController')->only('update');
|
||||
Route::prefix('poller')->group(function () {
|
||||
Route::get('', 'PollerController@pollerTab')->name('poller.index');
|
||||
@@ -166,6 +168,7 @@ Route::middleware(['auth'])->group(function () {
|
||||
Route::get('graph', 'GraphController')->name('ajax.select.graph');
|
||||
Route::get('graph-aggregate', 'GraphAggregateController')->name('ajax.select.graph-aggregate');
|
||||
Route::get('graylog-streams', 'GraylogStreamsController')->name('ajax.select.graylog-streams');
|
||||
Route::get('inventory', 'InventoryController')->name('ajax.select.inventory');
|
||||
Route::get('syslog', 'SyslogController')->name('ajax.select.syslog');
|
||||
Route::get('location', 'LocationController')->name('ajax.select.location');
|
||||
Route::get('munin', 'MuninPluginController')->name('ajax.select.munin');
|
||||
@@ -185,6 +188,7 @@ Route::middleware(['auth'])->group(function () {
|
||||
Route::post('eventlog', 'EventlogController');
|
||||
Route::post('fdb-tables', 'FdbTablesController');
|
||||
Route::post('graylog', 'GraylogController');
|
||||
Route::post('inventory', 'InventoryController')->name('table.inventory');
|
||||
Route::post('location', 'LocationController');
|
||||
Route::post('mempools', 'MempoolsController');
|
||||
Route::post('outages', 'OutagesController');
|
||||
|
Reference in New Issue
Block a user