Merge pull request #11313 from snipe/fixes/nicer_suppliers_mfgs_ui

Nicer suppliers and manufacturers UI
This commit is contained in:
snipe 2022-06-14 17:14:53 -07:00 committed by GitHub
commit 693043e645
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 317 additions and 255 deletions

View file

@ -27,7 +27,6 @@ class AccessoriesController extends Controller
public function index(Request $request)
{
$this->authorize('view', Accessory::class);
$allowed_columns = ['id', 'name', 'model_number', 'eol', 'notes', 'created_at', 'min_amt', 'company_id'];
// This array is what determines which fields should be allowed to be sorted on ON the table itself, no relations
// Relations will be handled in query scopes a little further down.

View file

@ -35,7 +35,8 @@ class AssetMaintenancesController extends Controller
public function index(Request $request)
{
$this->authorize('view', Asset::class);
$maintenances = AssetMaintenance::with('asset', 'asset.model', 'asset.location', 'supplier', 'asset.company', 'admin');
$maintenances = AssetMaintenance::select('asset_maintenances.*')->with('asset', 'asset.model', 'asset.location', 'supplier', 'asset.company', 'admin');
if ($request->filled('search')) {
$maintenances = $maintenances->TextSearch($request->input('search'));
@ -45,6 +46,15 @@ class AssetMaintenancesController extends Controller
$maintenances->where('asset_id', '=', $request->input('asset_id'));
}
if ($request->filled('supplier_id')) {
$maintenances->where('supplier_id', '=', $request->input('supplier_id'));
}
if ($request->filled('asset_maintenance_type')) {
$maintenances->where('asset_maintenance_type', '=', $request->input('asset_maintenance_type'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($maintenances) && ($request->get('offset') > $maintenances->count())) ? $maintenances->count() : $request->get('offset', 0);
@ -64,6 +74,7 @@ class AssetMaintenancesController extends Controller
'asset_tag',
'asset_name',
'user_id',
'supplier'
];
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
@ -72,6 +83,9 @@ class AssetMaintenancesController extends Controller
case 'user_id':
$maintenances = $maintenances->OrderAdmin($order);
break;
case 'supplier':
$maintenances = $maintenances->OrderBySupplier($order);
break;
case 'asset_tag':
$maintenances = $maintenances->OrderByTag($order);
break;

View file

@ -162,6 +162,20 @@ class AssetMaintenance extends Model implements ICompanyableChild
* -----------------------------------------------
**/
/**
* Query builder scope to order on a supplier
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeOrderBySupplier($query, $order)
{
return $query->leftJoin('suppliers as suppliers_maintenances', 'asset_maintenances.supplier_id', '=', 'suppliers_maintenances.id')
->orderBy('suppliers_maintenances.name', $order);
}
/**
* Query builder scope to order on admin user
*

View file

@ -184,7 +184,7 @@ class Supplier extends SnipeModel
*/
public function addhttp($url)
{
if (! preg_match('~^(?:f|ht)tps?://~i', $url)) {
if (($url!='') && (! preg_match('~^(?:f|ht)tps?://~i', $url))) {
$url = 'http://'.$url;
}

View file

@ -9,6 +9,10 @@
@stop
@section('header_right')
<a href="{{ route('manufacturers.index') }}" class="btn btn-primary text-right" style="margin-right: 10px;">{{ trans('general.back') }}</a>
<div class="btn-group pull-right">
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">{{ trans('button.actions') }}
<span class="caret"></span>
@ -29,16 +33,58 @@
<ul class="nav nav-tabs">
<li class="active">
<a href="#assets" data-toggle="tab">Assets</a>
<a href="#assets" data-toggle="tab">
<span class="hidden-lg hidden-md">
<i class="fas fa-barcode fa-2x"></i>
</span>
<span class="hidden-xs hidden-sm">
{{ trans('general.assets') }}
{!! (($manufacturer->assets) && ($manufacturer->assets->count() > 0 )) ? '<badge class="badge badge-secondary">'.$manufacturer->assets->count().'</badge>' : '' !!}
</span>
</a>
</li>
<li>
<a href="#licenses" data-toggle="tab">Licenses</a>
<a href="#licenses" data-toggle="tab">
<span class="hidden-lg hidden-md">
<i class="far fa-save fa-2x"></i>
</span>
<span class="hidden-xs hidden-sm">
{{ trans('general.licenses') }}
{!! (($manufacturer->licenses) && ($manufacturer->licenses->count() > 0 )) ? '<badge class="badge badge-secondary">'.$manufacturer->licenses->count().'</badge>' : '' !!}
</span>
</a>
</li>
<li>
<a href="#accessories" data-toggle="tab">Accessories</a>
<a href="#accessories" data-toggle="tab">
<span class="hidden-lg hidden-md">
<i class="far fa-keyboard fa-2x"></i>
</span>
<span class="hidden-xs hidden-sm">
{{ trans('general.accessories') }}
{!! (($manufacturer->accessories) && ($manufacturer->accessories->count() > 0 )) ? '<badge class="badge badge-secondary">'.$manufacturer->accessories->count().'</badge>' : '' !!}
</span>
</a>
</li>
<li>
<a href="#consumables" data-toggle="tab">Consumables</a>
<a href="#consumables" data-toggle="tab">
<span class="hidden-lg hidden-md">
<i class="fas fa-tint fa-2x"></i>
</span>
<span class="hidden-xs hidden-sm">
{{ trans('general.consumables') }}
{!! (($manufacturer->consumables) && ($manufacturer->consumables->count() > 0 )) ? '<badge class="badge badge-secondary">'.$manufacturer->consumables->count().'</badge>' : '' !!}
</span>
</a>
</li>
</ul>

View file

@ -1,39 +1,95 @@
@extends('layouts/default')
{{-- Page title --}}
@section('title')
{{ trans('admin/suppliers/table.view') }} -
{{ $supplier->name }}
@parent
{{ trans('admin/suppliers/table.view') }} -
{{ $supplier->name }}
@parent
@stop
@section('header_right')
<a href="{{ route('suppliers.edit', $supplier->id) }}" class="btn btn-default pull-right">
{{ trans('admin/suppliers/table.update') }}</a>
<a href="{{ route('suppliers.index') }}" class="btn btn-primary text-right" style="margin-right: 10px;">{{ trans('general.back') }}</a>
@stop
{{-- Page content --}}
@section('content')
<div class="row">
<div class="row">
<div class="col-md-9">
<div class="nav-tabs-custom">
<ul class="nav nav-tabs hidden-print">
<li class="active">
<a href="#assets" data-toggle="tab">
<span class="hidden-lg hidden-md">
<i class="fas fa-barcode fa-2x" aria-hidden="true"></i>
</span>
<span class="hidden-xs hidden-sm">
{{ trans('general.assets') }}
{!! (($supplier->assets) && ($supplier->assets->count() > 0 )) ? '<badge class="badge badge-secondary">'.$supplier->assets->count().'</badge>' : '' !!}
</span>
</a>
</li>
<li>
<a href="#accessories" data-toggle="tab">
<span class="hidden-lg hidden-md">
<i class="far fa-keyboard fa-2x" aria-hidden="true"></i>
</span>
<span class="hidden-xs hidden-sm">
{{ trans('general.accessories') }}
{!! (($supplier->accessories) && ($supplier->accessories->count() > 0 )) ? '<badge class="badge badge-secondary">'.$supplier->accessories->count().'</badge>' : '' !!}
</span>
</a>
</li>
<li>
<a href="#licenses" data-toggle="tab">
<span class="hidden-lg hidden-md">
<i class="far fa-save fa-2x" aria-hidden="true"></i>
</span>
<span class="hidden-xs hidden-sm">
{{ trans('general.licenses') }}
{!! (($supplier->licenses) && ($supplier->licenses->count() > 0 )) ? '<badge class="badge badge-secondary">'.$supplier->licenses->count().'</badge>' : '' !!}
</span>
</a>
</li>
<li>
<a href="#maintenances" data-toggle="tab">
<span class="hidden-lg hidden-md">
<i class="fas fa-wrench fa-2x"></i>
</span>
<span class="hidden-xs hidden-sm">
{{ trans('admin/asset_maintenances/general.asset_maintenances') }}
{!! (($supplier->asset_maintenances) && ($supplier->asset_maintenances->count() > 0 )) ? '<badge class="badge badge-secondary">'.$supplier->asset_maintenances->count().'</badge>' : '' !!}
</span>
</a>
</li>
</ul>
<!-- start tables -->
<div class="tab-content">
<div class="box box-default">
<div class="box-header with-border">
<div class="box-heading">
<h2 class="box-title"> {{ trans('general.assets') }}</h2>
</div>
</div><!-- /.box-header -->
<div class="box-body">
<!-- checked out suppliers table -->
<div class="table-responsive">
<div class="tab-pane active" id="assets">
<h2 class="box-title">{{ trans('general.assets') }}</h2>
<div class="table table-responsive">
@include('partials.asset-bulk-actions')
<table
data-cookie-id-table="suppliersAssetsTable"
data-columns="{{ \App\Presenters\AssetPresenter::dataTableLayout() }}"
data-pagination="true"
data-id-table="suppliersAssetsTable"
data-search="true"
@ -43,183 +99,113 @@
data-show-export="true"
data-show-refresh="true"
data-sort-order="asc"
data-toolbar="#assetsBulkEditToolbar"
data-bulk-button-id="#bulkAssetEditButton"
data-bulk-form-id="#assetsBulkForm"
data-click-to-select="true"
id="suppliersAssetsTable"
class="table table-striped snipe-table"
data-url="{{route('api.assets.index', ['supplier_id' => $supplier->id])}}"
data-url="{{route('api.assets.index', ['supplier_id' => $supplier->id]) }}"
data-export-options='{
"fileName": "export-{{ str_slug($supplier->name) }}-assets-{{ date('Y-m-d') }}",
"fileName": "export-suppliers-{{ str_slug($supplier->name) }}-assets-{{ date('Y-m-d') }}",
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
}'>
<thead>
<tr>
<th data-searchable="false" data-visible="false" data-sortable="true" data-field="id">{{ trans('general.id') }}</th>
<th data-searchable="false" data-visible="true" data-sortable="true" data-formatter="imageFormatter" data-field="image">{{ trans('admin/hardware/table.image') }}</th>
<th data-searchable="false" data-sortable="true" data-formatter="hardwareLinkFormatter" data-field="name">{{ trans('general.name') }}</th>
<th data-searchable="false" data-formatter="modelsLinkObjFormatter" data-sortable="false" data-field="model">{{ trans('admin/hardware/form.model') }}</th>
<th data-searchable="false" data-sortable="false" data-field="asset_tag" data-formatter="hardwareLinkFormatter">{{ trans('admin/hardware/form.tag') }}</th>
<th data-searchable="false" data-sortable="false" data-field="serial">{{ trans('admin/hardware/form.serial') }}</th>
<th data-searchable="false" data-visible="false" data-sortable="true" data-field="category" data-formatter="categoriesLinkObjFormatter">{{ trans('general.category') }}</th>
<th data-field="purchase_cost" data-footer-formatter="sumFormatter">{{ trans('general.purchase_cost') }}</th>
<th data-searchable="false" data-sortable="false" data-field="checkincheckout" data-formatter="hardwareInOutFormatter">{{ trans('general.checkin') }}/{{ trans('general.checkout') }}</th>
<th data-searchable="false" data-sortable="false" data-field="actions" data-formatter="hardwareActionsFormatter">{{ trans('table.actions') }}</th>
</tr>
</thead>
</table>
</div><!-- /.table-responsive -->
</div><!-- /.box-body -->
</div> <!--/.box-->
</div><!-- /.tab-pane -->
<div class="box box-default">
<div class="box-header with-border">
<div class="box-heading">
<h2 class="box-title"> {{ trans('general.accessories') }}</h2>
</div>
</div><!-- /.box-header -->
<div class="box-body">
<div class="table-responsive">
<div class="tab-pane" id="accessories">
<h2 class="box-title">{{ trans('general.accessories') }}</h2>
<div class="table table-responsive">
<table
data-columns="{{ \App\Presenters\AccessoryPresenter::dataTableLayout() }}"
data-cookie-id-table="suppliersAccessoriesTable"
data-cookie-id-table="accessoriesListingTable"
data-pagination="true"
data-id-table="suppliersAccessoriesTable"
data-id-table="accessoriesListingTable"
data-search="true"
data-side-pagination="server"
data-show-columns="true"
data-show-export="true"
data-show-refresh="true"
data-sort-order="asc"
id="suppliersAccessoriesTable"
id="accessoriesListingTable"
class="table table-striped snipe-table"
data-url="{{route('api.accessories.index', ['supplier_id' => $supplier->id])}}"
data-url="{{route('api.accessories.index', ['supplier_id' => $supplier->id]) }}"
data-export-options='{
"fileName": "export-{{ str_slug($supplier->name) }}-accessories-{{ date('Y-m-d') }}",
"fileName": "export-suppliers-{{ str_slug($supplier->name) }}-accessories-{{ date('Y-m-d') }}",
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
}'>
</table>
</div><!-- /.table-responsive -->
</div><!-- /.box-body -->
</div> <!--/.box-->
</div><!-- /.tab-pane -->
<div class="tab-pane" id="licenses">
<h2 class="box-title">{{ trans('general.licenses') }}</h2>
<div class="box box-default">
@if ($supplier->id)
<div class="box-header with-border">
<div class="box-heading">
<h2 class="box-title"> {{ trans('general.licenses') }}</h2>
</div>
</div><!-- /.box-header -->
@endif
<div class="box-body">
<div class="table-responsive">
<div class="table table-responsive">
<table
data-columns="{{ \App\Presenters\LicensePresenter::dataTableLayout() }}"
data-cookie-id-table="suppliersLicensesTable"
data-cookie-id-table="licensesListingTable"
data-pagination="true"
data-id-table="suppliersLicensesTable"
data-id-table="licensesListingTable"
data-search="true"
data-show-footer="true"
data-side-pagination="server"
data-show-columns="true"
data-show-export="true"
data-show-refresh="true"
data-sort-order="asc"
id="suppliersLicensesTable"
id="licensesListingTable"
class="table table-striped snipe-table"
data-url="{{route('api.licenses.index', ['supplier_id' => $supplier->id])}}"
data-url="{{route('api.licenses.index', ['supplier_id' => $supplier->id]) }}"
data-export-options='{
"fileName": "export-{{ str_slug($supplier->name) }}-licenses-{{ date('Y-m-d') }}",
"fileName": "export-suppliers-{{ str_slug($supplier->name) }}-licenses-{{ date('Y-m-d') }}",
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
}'>
</table>
</div><!-- /.table-responsive -->
</div><!-- /.tab-pane -->
<div class="tab-pane" id="maintenances">
<h2 class="box-title">{{ trans('admin/asset_maintenances/general.asset_maintenances') }}</h2>
<div class="table table-responsive">
<table
data-columns="{{ \App\Presenters\AssetMaintenancesPresenter::dataTableLayout() }}"
data-cookie-id-table="maintenancesTable"
data-pagination="true"
data-id-table="maintenancesTable"
data-search="true"
data-side-pagination="server"
data-show-columns="true"
data-show-export="true"
data-show-refresh="true"
data-sort-order="asc"
id="maintenancesTable"
class="table table-striped snipe-table"
data-url="{{ route('api.maintenances.index', ['supplier_id' => $supplier->id])}}"
data-export-options='{
"fileName": "export-suppliers-{{ str_slug($supplier->name) }}-maintenances-{{ date('Y-m-d') }}",
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
}'>
</table>
</div><!-- /.table-responsive -->
</div><!-- /.box-body -->
</div> <!--/.box-->
</div><!-- /.tab-pane -->
<div class="box box-default">
@if ($supplier->id)
<div class="box-header with-border">
<div class="box-heading">
<h2 class="box-title"> {{ trans('general.improvements') }}</h2>
</div>
</div><!-- /.box-header -->
@endif
<div class="box-body">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th class="col-md-2"><span class="line"></span>{{ trans('admin/asset_maintenances/table.asset_name') }}</th>
<th class="col-md-2"><span class="line"></span>{{ trans('admin/asset_maintenances/form.asset_maintenance_type') }}</th>
<th class="col-md-2"><span class="line"></span>{{ trans('admin/asset_maintenances/form.start_date') }}</th>
<th class="col-md-2"><span class="line"></span>{{ trans('admin/asset_maintenances/form.completion_date') }}</th>
<th class="col-md-2"><span class="line"></span>{{ trans('admin/asset_maintenances/table.is_warranty') }}</th>
<th class="col-md-2"><span class="line"></span>{{ trans('admin/asset_maintenances/form.cost') }}</th>
<th class="col-md-1"><span class="line"></span>{{ trans('table.actions') }}</th>
</tr>
</thead>
<tbody>
<?php $totalCost = 0; ?>
@if ($supplier->asset_maintenances)
@foreach ($supplier->asset_maintenances as $improvement)
@if (is_null($improvement->deleted_at))
<tr>
<td>
@if ($improvement->asset)
<a href="{{ route('hardware.show', $improvement->asset_id) }}">{{ $improvement->asset->name }}</a>
@else
(deleted asset)
@endif
</td>
<td>{{ $improvement->asset_maintenance_type }}</td>
<td>{{ $improvement->start_date }}</td>
<td>{{ $improvement->completion_date }}</td>
<td>{{ $improvement->is_warranty ? trans('admin/asset_maintenances/message.warranty') : trans('admin/asset_maintenances/message.not_warranty') }}</td>
<td>{{ $snipeSettings->default_currency. ' '. Helper::formatCurrencyOutput($improvement->cost) }}</td>
<?php $totalCost += $improvement->cost; ?>
<td><a href="{{ route('maintenances.edit', $improvement->id) }}" class="btn btn-warning"><i class="fas fa-pencil-alt icon-white" aria-hidden="true"></i></a>
</td>
</tr>
@endif
@endforeach
@endif
</tbody>
<tfoot>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>{{ $snipeSettings->default_currency . ' '.Helper::formatCurrencyOutput($totalCost) }}</td>
</tr>
</tfoot>
</table>
</div><!-- /.table-responsive -->
</div><!-- /.box-body -->
</div> <!--/.box-->
</div> <!--/col-md-9-->
</div><!--/.col-md-9-->
</div><!--/.col-md-9-->
</div><!--/.col-md-9-->
<!-- side address column -->
<div class="col-md-3">
@if (($supplier->state!='') && ($supplier->country!='') && (config('services.google.maps_api_key')))
@if (($supplier->address!='') && ($supplier->state!='') && ($supplier->country!='') && (config('services.google.maps_api_key')))
<div class="col-md-12 text-center" style="padding-bottom: 20px;">
<img src="https://maps.googleapis.com/maps/api/staticmap?markers={{ urlencode($supplier->address.','.$supplier->city.' '.$supplier->state.' '.$supplier->country.' '.$supplier->zip) }}&size=500x300&maptype=roadmap&key={{ config('services.google.maps_api_key') }}" class="img-responsive img-thumbnail" alt="Map">
</div>
@ -227,19 +213,19 @@
<ul class="list-unstyled" style="line-height: 25px; padding-bottom: 20px; padding-top: 20px;">
@if ($supplier->contact)
@if ($supplier->contact!='')
<li><i class="fas fa-user" aria-hidden="true"></i> {{ $supplier->contact }}</li>
@endif
@if ($supplier->phone)
@if ($supplier->phone!='')
<li><i class="fas fa-phone"></i>
<a href="tel:{{ $supplier->phone }}">{{ $supplier->phone }}</a>
</li>
@endif
@if ($supplier->fax)
@if ($supplier->fax!='')
<li><i class="fas fa-print"></i> {{ $supplier->fax }}</li>
@endif
@if ($supplier->email)
@if ($supplier->email!='')
<li>
<i class="far fa-envelope"></i>
<a href="mailto:{{ $supplier->email }}">
@ -248,14 +234,14 @@
</li>
@endif
@if ($supplier->url)
@if ($supplier->url!='')
<li>
<i class="fas fa-globe-americas"></i>
<a href="{{ $supplier->url }}" target="_new">{{ $supplier->url }}</a>
</li>
@endif
@if ($supplier->address)
@if ($supplier->address!='')
<li><br>
{{ $supplier->address }}
@ -270,7 +256,7 @@
</li>
@endif
@if ($supplier->notes)
@if ($supplier->notes!='')
<li><i class="fa fa-comment"></i> {{ $supplier->notes }}</li>
@endif
@ -282,13 +268,16 @@
@endif
</div> <!--/col-md-3-->
</div> <!--/row-->
</div>
</div>
@stop
@section('moar_scripts')
@include ('partials.bootstrap-table', [
'showFooter' => true,
'exportFile' => 'locations-export',
'search' => true
])
@stop