mirror of
https://github.com/snipe/snipe-it.git
synced 2024-12-27 14:39:49 -08:00
Merge remote-tracking branch 'origin/develop'
This commit is contained in:
commit
88ae8858e8
|
@ -27,7 +27,7 @@ class LocationsController extends Controller
|
|||
$allowed_columns = [
|
||||
'id', 'name', 'address', 'address2', 'city', 'state', 'country', 'zip', 'created_at',
|
||||
'updated_at', 'manager_id', 'image',
|
||||
'assigned_assets_count', 'users_count', 'assets_count', 'currency', 'ldap_ou', ];
|
||||
'assigned_assets_count', 'users_count', 'assets_count','assigned_assets_count', 'assets_location_count', 'rtd_assets_count', 'currency', 'ldap_ou', ];
|
||||
|
||||
$locations = Location::with('parent', 'manager', 'children')->select([
|
||||
'locations.id',
|
||||
|
@ -46,7 +46,8 @@ class LocationsController extends Controller
|
|||
'locations.ldap_ou',
|
||||
'locations.currency',
|
||||
])->withCount('assignedAssets as assigned_assets_count')
|
||||
->withCount('assets as assets_count')
|
||||
->withCount('assets as assets_location_count')
|
||||
->withCount('rtd_assets as rtd_assets_count')
|
||||
->withCount('users as users_count');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
|
@ -156,8 +157,10 @@ class LocationsController extends Controller
|
|||
'locations.currency',
|
||||
])
|
||||
->withCount('assignedAssets as assigned_assets_count')
|
||||
->withCount('assets as assets_count')
|
||||
->withCount('users as users_count')->findOrFail($id);
|
||||
->withCount('assets as assets_location_count')
|
||||
->withCount('rtd_assets as rtd_assets_count')
|
||||
->withCount('users as users_count')
|
||||
->findOrFail($id);
|
||||
|
||||
return (new LocationsTransformer)->transformLocation($location);
|
||||
}
|
||||
|
|
|
@ -44,7 +44,8 @@ class LocationsTransformer
|
|||
'country' => ($location->country) ? e($location->country) : null,
|
||||
'zip' => ($location->zip) ? e($location->zip) : null,
|
||||
'assigned_assets_count' => (int) $location->assigned_assets_count,
|
||||
'assets_count' => (int) $location->assets_count,
|
||||
'assets_location_count' => (int) $location->assets_location_count,
|
||||
'rtd_assets_count' => (int) $location->rtd_assets_count,
|
||||
'users_count' => (int) $location->users_count,
|
||||
'currency' => ($location->currency) ? e($location->currency) : null,
|
||||
'ldap_ou' => ($location->ldap_ou) ? e($location->ldap_ou) : null,
|
||||
|
|
|
@ -90,6 +90,14 @@ class Location extends SnipeModel
|
|||
'parent' => ['name'],
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether or not this location can be deleted
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v3.0]
|
||||
* @return bool
|
||||
*/
|
||||
public function isDeletable()
|
||||
{
|
||||
return Gate::allows('delete', $this)
|
||||
|
@ -98,12 +106,25 @@ class Location extends SnipeModel
|
|||
&& ($this->users()->count() === 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the user -> location relationship
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function users()
|
||||
{
|
||||
return $this->hasMany(\App\Models\User::class, 'location_id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find assets with this location as their location_id
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function assets()
|
||||
{
|
||||
return $this->hasMany(\App\Models\Asset::class, 'location_id')
|
||||
|
@ -114,6 +135,14 @@ class Location extends SnipeModel
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Establishes the asset -> rtd_location relationship
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function rtd_assets()
|
||||
{
|
||||
/* This used to have an ...->orHas() clause that referred to
|
||||
|
@ -123,48 +152,93 @@ class Location extends SnipeModel
|
|||
It is arguable that we should have a '...->whereNull('assigned_to')
|
||||
bit in there, but that isn't always correct either (in the case
|
||||
where a user has no location, for example).
|
||||
|
||||
In all likelyhood, we need to denorm an "effective_location" column
|
||||
into Assets to make this slightly less miserable.
|
||||
*/
|
||||
return $this->hasMany(\App\Models\Asset::class, 'rtd_location_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the consumable -> location relationship
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function consumables()
|
||||
{
|
||||
return $this->hasMany(\App\Models\Consumable::class, 'location_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the component -> location relationship
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function components()
|
||||
{
|
||||
return $this->hasMany(\App\Models\Component::class, 'location_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the component -> accessory relationship
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function accessories()
|
||||
{
|
||||
return $this->hasMany(\App\Models\Accessory::class, 'location_id');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Find the parent of a location
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v2.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function parent()
|
||||
{
|
||||
return $this->belongsTo(self::class, 'parent_id', 'id')
|
||||
->with('parent');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find the manager of a location
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v2.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function manager()
|
||||
{
|
||||
return $this->belongsTo(\App\Models\User::class, 'manager_id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find children of a location
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v2.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function children()
|
||||
{
|
||||
return $this->hasMany(self::class, 'parent_id')
|
||||
->with('children');
|
||||
}
|
||||
|
||||
// I don't think we need this anymore since we de-normed location_id in assets?
|
||||
/**
|
||||
* Establishes the asset -> location assignment relationship
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function assignedAssets()
|
||||
{
|
||||
return $this->morphMany(\App\Models\Asset::class, 'assigned', 'assigned_type', 'assigned_to')->withTrashed();
|
||||
|
|
|
@ -51,21 +51,32 @@ class LocationPresenter extends Presenter
|
|||
],
|
||||
|
||||
[
|
||||
'field' => 'assets_count',
|
||||
'field' => 'assets_location_count',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('admin/locations/table.assets_rtd'),
|
||||
'title' => trans('admin/locations/message.current_location'),
|
||||
'visible' => true,
|
||||
],
|
||||
|
||||
[
|
||||
'field' => 'rtd_assets_count',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('admin/hardware/form.default_location'),
|
||||
'visible' => false,
|
||||
],
|
||||
|
||||
[
|
||||
'field' => 'assigned_assets_count',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('admin/locations/table.assets_checkedout'),
|
||||
'title' => trans('admin/locations/message.assigned_assets'),
|
||||
'visible' => true,
|
||||
],
|
||||
|
||||
[
|
||||
'field' => 'users_count',
|
||||
'searchable' => false,
|
||||
|
|
|
@ -6,6 +6,8 @@ return array(
|
|||
'assoc_users' => 'This location is currently associated with at least one user and cannot be deleted. Please update your users to no longer reference this location and try again. ',
|
||||
'assoc_assets' => 'This location is currently associated with at least one asset and cannot be deleted. Please update your assets to no longer reference this location and try again. ',
|
||||
'assoc_child_loc' => 'This location is currently the parent of at least one child location and cannot be deleted. Please update your locations to no longer reference this location and try again. ',
|
||||
'assigned_assets' => 'Assigned Assets',
|
||||
'current_location' => 'Current Location',
|
||||
|
||||
|
||||
'create' => array(
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
@section('header_right')
|
||||
@can('create', \App\Models\Accessory::class)
|
||||
<a href="{{ route('accessories.create') }}" class="btn btn-primary pull-right"> {{ trans('general.create') }}</a>
|
||||
<a href="{{ route('accessories.create') }}" accesskey="n" class="btn btn-primary pull-right"> {{ trans('general.create') }}</a>
|
||||
@endcan
|
||||
@stop
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
@section('header_right')
|
||||
@can('create', \App\Models\Component::class)
|
||||
<a href="{{ route('components.create') }}" class="btn btn-primary pull-right"> {{ trans('general.create') }}</a>
|
||||
<a href="{{ route('components.create') }}" accesskey="n" class="btn btn-primary pull-right"> {{ trans('general.create') }}</a>
|
||||
@endcan
|
||||
@stop
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
@section('header_right')
|
||||
@can('create', \App\Models\Consumable::class)
|
||||
<a href="{{ route('consumables.create') }}" class="btn btn-primary pull-right"> {{ trans('general.create') }}</a>
|
||||
<a href="{{ route('consumables.create') }}" accesskey="n" class="btn btn-primary pull-right"> {{ trans('general.create') }}</a>
|
||||
@endcan
|
||||
@stop
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
<a href="{{ route('reports/custom') }}" style="margin-right: 5px;" class="btn btn-default">
|
||||
{{ trans('admin/hardware/general.custom_export') }}</a>
|
||||
@can('create', \App\Models\Asset::class)
|
||||
<a href="{{ route('hardware.create') }}" class="btn btn-primary pull-right"></i> {{ trans('general.create') }}</a>
|
||||
<a href="{{ route('hardware.create') }}" accesskey="n" class="btn btn-primary pull-right"></i> {{ trans('general.create') }}</a>
|
||||
@endcan
|
||||
|
||||
@stop
|
||||
|
|
|
@ -131,7 +131,7 @@
|
|||
<ul class="nav navbar-nav">
|
||||
@can('index', \App\Models\Asset::class)
|
||||
<li aria-hidden="true"{!! (Request::is('hardware*') ? ' class="active"' : '') !!} tabindex="-1">
|
||||
<a href="{{ url('hardware') }}" tabindex="-1">
|
||||
<a href="{{ url('hardware') }}" accesskey="1" tabindex="-1">
|
||||
<i class="fas fa-barcode fa-fw" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.assets') }}</span>
|
||||
</a>
|
||||
|
@ -139,7 +139,7 @@
|
|||
@endcan
|
||||
@can('view', \App\Models\License::class)
|
||||
<li aria-hidden="true"{!! (Request::is('licenses*') ? ' class="active"' : '') !!} tabindex="-1">
|
||||
<a href="{{ route('licenses.index') }}" tabindex="-1">
|
||||
<a href="{{ route('licenses.index') }}" accesskey="2" tabindex="-1">
|
||||
<i class="far fa-save fa-fw"></i>
|
||||
<span class="sr-only">{{ trans('general.licenses') }}</span>
|
||||
</a>
|
||||
|
@ -147,7 +147,7 @@
|
|||
@endcan
|
||||
@can('index', \App\Models\Accessory::class)
|
||||
<li aria-hidden="true"{!! (Request::is('accessories*') ? ' class="active"' : '') !!} tabindex="-1">
|
||||
<a href="{{ route('accessories.index') }}" tabindex="-1">
|
||||
<a href="{{ route('accessories.index') }}" accesskey="3" tabindex="-1">
|
||||
<i class="far fa-keyboard fa-fw"></i>
|
||||
<span class="sr-only">{{ trans('general.accessories') }}</span>
|
||||
</a>
|
||||
|
@ -155,7 +155,7 @@
|
|||
@endcan
|
||||
@can('index', \App\Models\Consumable::class)
|
||||
<li aria-hidden="true"{!! (Request::is('consumables*') ? ' class="active"' : '') !!}>
|
||||
<a href="{{ url('consumables') }}" tabindex="-1">
|
||||
<a href="{{ url('consumables') }}" accesskey="4" tabindex="-1">
|
||||
<i class="fas fa-tint fa-fw"></i>
|
||||
<span class="sr-only">{{ trans('general.consumables') }}</span>
|
||||
</a>
|
||||
|
@ -163,7 +163,7 @@
|
|||
@endcan
|
||||
@can('view', \App\Models\Component::class)
|
||||
<li aria-hidden="true"{!! (Request::is('components*') ? ' class="active"' : '') !!}>
|
||||
<a href="{{ route('components.index') }}" tabindex="-1">
|
||||
<a href="{{ route('components.index') }}" accesskey="5" tabindex="-1">
|
||||
<i class="far fa-hdd fa-fw"></i>
|
||||
<span class="sr-only">{{ trans('general.components') }}</span>
|
||||
</a>
|
||||
|
@ -571,7 +571,7 @@
|
|||
|
||||
@can('view', \App\Models\User::class)
|
||||
<li{!! (Request::is('users*') ? ' class="active"' : '') !!}>
|
||||
<a href="{{ route('users.index') }}">
|
||||
<a href="{{ route('users.index') }}" accesskey="6">
|
||||
<i class="fas fa-users fa-fw"></i>
|
||||
<span>{{ trans('general.people') }}</span>
|
||||
</a>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
@section('header_right')
|
||||
@can('create', \App\Models\License::class)
|
||||
<a href="{{ route('licenses.create') }}" class="btn btn-primary pull-right">
|
||||
<a href="{{ route('licenses.create') }}" accesskey="n" class="btn btn-primary pull-right">
|
||||
{{ trans('general.create') }}
|
||||
</a>
|
||||
@endcan
|
||||
|
|
|
@ -37,12 +37,13 @@
|
|||
<i class="fas fa-barcode fa-2x" aria-hidden="true"></i>
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('general.assets') }}
|
||||
{{ trans('admin/locations/message.current_location') }}
|
||||
{!! (($location->assets) && ($location->assets()->AssetsForShow()->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($location->assets()->AssetsForShow()->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
<a href="#rtd_assets" data-toggle="tab">
|
||||
<span class="hidden-lg hidden-md">
|
||||
|
@ -55,6 +56,18 @@
|
|||
</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#assets_assigned" 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('admin/locations/message.assigned_assets') }}
|
||||
{!! (($location->rtd_assets) && ($location->assignedAssets()->AssetsForShow()->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($location->assignedAssets()->AssetsForShow()->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
<a href="#accessories" data-toggle="tab">
|
||||
|
@ -127,7 +140,7 @@
|
|||
</div><!-- /.tab-pane -->
|
||||
|
||||
<div class="tab-pane" id="assets">
|
||||
<h2 class="box-title">{{ trans('general.assets') }}</h2>
|
||||
<h2 class="box-title">{{ trans('admin/locations/message.current_location') }}</h2>
|
||||
|
||||
<div class="table table-responsive">
|
||||
@include('partials.asset-bulk-actions')
|
||||
|
@ -158,6 +171,40 @@
|
|||
</div><!-- /.table-responsive -->
|
||||
</div><!-- /.tab-pane -->
|
||||
|
||||
<div class="tab-pane" id="assets_assigned">
|
||||
<h2 class="box-title">
|
||||
{{ trans('admin/locations/message.assigned_assets') }}
|
||||
</h2>
|
||||
|
||||
<div class="table table-responsive">
|
||||
@include('partials.asset-bulk-actions', ['id_divname' => 'AssignedAssetsBulkEditToolbar', 'id_formname' => 'assignedAssetsBulkForm', 'id_button' => 'AssignedbulkAssetEditButton'])
|
||||
<table
|
||||
data-columns="{{ \App\Presenters\AssetPresenter::dataTableLayout() }}"
|
||||
data-cookie-id-table="assetsAssignedListingTable"
|
||||
data-pagination="true"
|
||||
data-id-table="assetsAssignedListingTable"
|
||||
data-search="true"
|
||||
data-side-pagination="server"
|
||||
data-show-columns="true"
|
||||
data-show-export="true"
|
||||
data-show-refresh="true"
|
||||
data-sort-order="asc"
|
||||
data-toolbar="#AssignedAssetsBulkEditToolbar"
|
||||
data-bulk-button-id="#AssignedbulkAssetEditButton"
|
||||
data-bulk-form-id="#assignedAssetsBulkForm"
|
||||
data-click-to-select="true"
|
||||
id="assetsListingTable"
|
||||
class="table table-striped snipe-table"
|
||||
data-url="{{route('api.assets.index', ['assigned_to' => $location->id, 'assigned_type' => \App\Models\Location::class]) }}"
|
||||
data-export-options='{
|
||||
"fileName": "export-locations-{{ str_slug($location->name) }}-assets-{{ date('Y-m-d') }}",
|
||||
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
|
||||
}'>
|
||||
</table>
|
||||
|
||||
</div><!-- /.table-responsive -->
|
||||
</div><!-- /.tab-pane -->
|
||||
|
||||
<div class="tab-pane" id="rtd_assets">
|
||||
<h2 class="box-title">{{ trans('admin/hardware/form.default_location') }}</h2>
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
@can('delete', \App\Models\Asset::class)
|
||||
<option value="delete">{{ trans('button.delete') }}</option>
|
||||
@endcan
|
||||
<option value="labels">{{ trans_choice('button.generate_labels', 2) }}</option>
|
||||
<option value="labels" accesskey="l">{{ trans_choice('button.generate_labels', 2) }}</option>
|
||||
</select>
|
||||
|
||||
<button class="btn btn-primary" id="{{ (isset($id_button)) ? $id_button : 'bulkAssetEditButton' }}" disabled>{{ trans('button.go') }}</button>
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
<div class="box-footer text-right">
|
||||
<a class="btn btn-link text-left" href="{{ URL::previous() }}">{{ trans('button.cancel') }}</a>
|
||||
<button type="submit" class="btn btn-primary"><i class="fas fa-check icon-white" aria-hidden="true"></i> {{ trans('general.save') }}</button>
|
||||
<button type="submit" accesskey="s" class="btn btn-primary"><i class="fas fa-check icon-white" aria-hidden="true"></i> {{ trans('general.save') }}</button>
|
||||
</div>
|
||||
<!-- / partials/forms/edit/submit.blade.php -->
|
||||
|
|
|
@ -568,7 +568,7 @@
|
|||
</div><!-- /.tab-pane -->
|
||||
</div><!-- /.tab-content -->
|
||||
<div class="box-footer text-right">
|
||||
<button type="submit" class="btn btn-primary"><i class="fas fa-check icon-white" aria-hidden="true"></i> {{ trans('general.save') }}</button>
|
||||
<button type="submit" accesskey="s" class="btn btn-primary"><i class="fas fa-check icon-white" aria-hidden="true"></i> {{ trans('general.save') }}</button>
|
||||
</div>
|
||||
</div><!-- nav-tabs-custom -->
|
||||
</form>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
@if ($snipeSettings->ldap_enabled == 1)
|
||||
<a href="{{ route('ldap/user') }}" class="btn btn-default pull-right"><span class="fas fa-sitemap"></span>{{trans('general.ldap_sync')}}</a>
|
||||
@endif
|
||||
<a href="{{ route('users.create') }}" class="btn btn-primary pull-right" style="margin-right: 5px;"> {{ trans('general.create') }}</a>
|
||||
<a href="{{ route('users.create') }}" accesskey="n" class="btn btn-primary pull-right" style="margin-right: 5px;"> {{ trans('general.create') }}</a>
|
||||
@endcan
|
||||
|
||||
@if (request('status')=='deleted')
|
||||
|
|
Loading…
Reference in a new issue