Merge pull request #12035 from snipe/features/added_new_tab_to_locations

Features/added new tab to locations
This commit is contained in:
snipe 2022-10-26 00:32:07 -07:00 committed by GitHub
commit 0bc0a116aa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 155 additions and 17 deletions

View file

@ -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);
}

View file

@ -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,

View file

@ -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();

View file

@ -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,

View file

@ -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(

View file

@ -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>