Assorted fixes (#3923)

* Fix some n+1 problems

* Use route in notification dropdown to make sure we link to correct page

* Work on better UI support for checkout to non-user.  Fix links on index bootstrap table, work towards eliminating assignedUser

* Remove Asset::assigneduser() relationship.  Instead add a checkedOutToUser() method and/or port to using assignedTo()

* Adjust string to fit new reality

* Fix #3780.  Move the consumables getDataView method to the ApiController.  Not entirely RESTful, but it's a weird method that probably doesn't need its own controller and the functionality would be strange to stack on the userscontroller...

* Fix file uploads to assets and restore the delete route.

* Add asset maintence edit action to index.

* Suppliers asset list should link to the related asset, not to the supplier with same ID.

* Asset models page should use polymorphic formatter on assigned to to better handle assorted item types.

* Comment out more assigneduser fallacy until we figure out the query builder approach to searching for location text.
This commit is contained in:
Daniel Meltzer 2017-09-05 20:54:58 -04:00 committed by snipe
parent 10f322198f
commit 987536930c
31 changed files with 193 additions and 143 deletions

View file

@ -44,14 +44,14 @@ class SendExpectedCheckinAlerts extends Command
{
$whenNotify = Carbon::now()->addDays(7);
$assets = Asset::with('assigneduser')->whereNotNull('expected_checkin')->where('expected_checkin', '<=', $whenNotify)->get();
$assets = Asset::with('assignedTo')->whereNotNull('expected_checkin')->where('expected_checkin', '<=', $whenNotify)->get();
$this->info($whenNotify.' is deadline');
$this->info($assets->count().' assets');
foreach ($assets as $asset) {
if ($asset->assigneduser) {
$asset->assigneduser->notify((new ExpectedCheckinNotification($asset)));
if ($asset->assignedTo && $asset->checkoutOutToUser()) {
$asset->assignedTo->notify((new ExpectedCheckinNotification($asset)));
//$this->info($asset);
}
}

View file

@ -1,16 +1,17 @@
<?php
namespace App\Http\Controllers\Api;
use App\Models\AssetMaintenance;
use Carbon\Carbon;
use App\Models\Company;
use App\Models\Asset;
use App\Helpers\Helper;
use Auth;
use Gate;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Transformers\AssetMaintenancesTransformer;
use App\Models\Asset;
use App\Models\AssetMaintenance;
use App\Models\Company;
use Auth;
use Carbon\Carbon;
use Gate;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Input;
/**
* This controller handles all actions related to Asset Maintenance for

View file

@ -84,9 +84,8 @@ class AssetsController extends Controller
}
$assets = Company::scopeCompanyables(Asset::select('assets.*'))->with(
'assetLoc', 'assetstatus', 'defaultLoc', 'assetlog', 'company',
'model.category', 'model.manufacturer', 'model.fieldset', 'assigneduser','supplier');
'assetloc', 'assetstatus', 'defaultLoc', 'assetlog', 'company',
'model.category', 'model.manufacturer', 'model.fieldset','supplier');
// If we should search on everything
if (($request->has('search')) && (count($filter) == 0)) {
$assets->TextSearch($request->input('search'));
@ -97,7 +96,6 @@ class AssetsController extends Controller
}
}
// These are used by the API to query against specific ID numbers
if ($request->has('status_id')) {
$assets->where('status_id', '=', $request->input('status_id'));

View file

@ -148,4 +148,47 @@ class ConsumablesController extends Controller
$consumable->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/consumables/message.delete.success')));
}
/**
* Returns a JSON response containing details on the users associated with this consumable.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see ConsumablesController::getView() method that returns the form.
* @since [v1.0]
* @param int $consumableId
* @return array
*/
public function getDataView($consumableId)
{
//$consumable = Consumable::find($consumableID);
$consumable = Consumable::with(array('consumableAssignments'=>
function ($query) {
$query->orderBy('created_at', 'DESC');
},
'consumableAssignments.admin'=> function ($query) {
},
'consumableAssignments.user'=> function ($query) {
},
))->find($consumableId);
// $consumable->load('consumableAssignments.admin','consumableAssignments.user');
if (!Company::isCurrentUserHasAccess($consumable)) {
return ['total' => 0, 'rows' => []];
}
$this->authorize('view', Component::class);
$rows = array();
foreach ($consumable->consumableAssignments as $consumable_assignment) {
$rows[] = [
'name' => $consumable_assignment->user->present()->nameUrl(),
'created_at' => ($consumable_assignment->created_at->format('Y-m-d H:i:s')=='-0001-11-30 00:00:00') ? '' : $consumable_assignment->created_at->format('Y-m-d H:i:s'),
'admin' => ($consumable_assignment->admin) ? $consumable_assignment->admin->present()->nameUrl() : '',
];
}
$consumableCount = $consumable->users->count();
$data = array('total' => $consumableCount, 'rows' => $rows);
return $data;
}
}

View file

@ -21,7 +21,7 @@ class LicensesController extends Controller
public function index(Request $request)
{
$this->authorize('view', License::class);
$licenses = Company::scopeCompanyables(License::with('company', 'licenseSeatsRelation', 'manufacturer'));
$licenses = Company::scopeCompanyables(License::with('company', 'licenseSeatsRelation', 'manufacturer', 'supplier'));
if ($request->has('search')) {
$licenses = $licenses->TextSearch($request->input('search'));

View file

@ -537,17 +537,18 @@ class AssetsController extends Controller
$this->authorize('checkin', $asset);
$admin = Auth::user();
$user = $asset->assignedUser;
if($asset->assignedType() == Asset::USER) {
$user = $asset->assignedTo;
}
if (is_null($target = $asset->assignedTo)) {
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.already_checked_in'));
}
// This is just used for the redirect
$return_to = $asset->assigned_to;
$asset->expected_checkin = null;
$asset->last_checkout = null;
$asset->assigned_to = null;
$asset->assignedTo()->disassociate($asset);
$asset->assigned_type = null;
$asset->accepted = null;
$asset->name = e(Input::get('name'));
@ -575,7 +576,7 @@ class AssetsController extends Controller
}
if ($backto=='user') {
return redirect()->to("admin/users/".$return_to.'/view')->with('success', trans('admin/hardware/message.checkin.success'));
return redirect()->to("admin/users/".$user->id.'/view')->with('success', trans('admin/hardware/message.checkin.success'));
}
return redirect()->route("hardware.index")->with('success', trans('admin/hardware/message.checkin.success'));
}
@ -957,7 +958,7 @@ class AssetsController extends Controller
* @since [v1.0]
* @return View
*/
public function getDeleteFile($assetId = null, $fileId = null)
public function deleteFile($assetId = null, $fileId = null)
{
$asset = Asset::find($assetId);
$this->authorize('update', $asset);

View file

@ -273,47 +273,4 @@ class ConsumablesController extends Controller
}
/**
* Returns a JSON response containing details on the users associated with this consumable.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see ConsumablesController::getView() method that returns the form.
* @since [v1.0]
* @param int $consumableId
* @return array
*/
public function getDataView($consumableId)
{
//$consumable = Consumable::find($consumableID);
$consumable = Consumable::with(array('consumableAssigments'=>
function ($query) {
$query->orderBy('created_at', 'DESC');
},
'consumableAssigments.admin'=> function ($query) {
},
'consumableAssigments.user'=> function ($query) {
},
))->find($consumableId);
// $consumable->load('consumableAssigments.admin','consumableAssigments.user');
if (!Company::isCurrentUserHasAccess($consumable)) {
return ['total' => 0, 'rows' => []];
}
$this->authorize('view', Component::class);
$rows = array();
foreach ($consumable->consumableAssigments as $consumable_assignment) {
$rows[] = [
'name' => $consumable_assignment->user->present()->nameUrl(),
'created_at' => ($consumable_assignment->created_at->format('Y-m-d H:i:s')=='-0001-11-30 00:00:00') ? '' : $consumable_assignment->created_at->format('Y-m-d H:i:s'),
'admin' => ($consumable_assignment->admin) ? $consumable_assignment->admin->present()->nameUrl() : '',
];
}
$consumableCount = $consumable->users->count();
$data = array('total' => $consumableCount, 'rows' => $rows);
return $data;
}
}

View file

@ -186,7 +186,7 @@ class ReportsController extends Controller
{
// Grab all the assets
$assets = Asset::with('model', 'assignedTo', 'assetstatus', 'defaultLoc', 'assetlog', 'company')
$assets = Asset::with( 'assignedTo', 'assetstatus', 'defaultLoc', 'assetloc', 'assetlog', 'company', 'model.category', 'model.depreciation')
->orderBy('created_at', 'DESC')->get();
return view('reports/depreciation', compact('assets'));
@ -390,7 +390,7 @@ class ReportsController extends Controller
*/
public function postCustom()
{
$assets = Asset::orderBy('created_at', 'DESC')->with('company', 'assigneduser', 'assetloc', 'defaultLoc', 'assigneduser.userloc', 'model', 'supplier', 'assetstatus', 'model.manufacturer')->get();
$assets = Asset::orderBy('created_at', 'DESC')->with('company', 'assignedTo', 'assetloc', 'defaultLoc', 'model', 'supplier', 'assetstatus', 'model.manufacturer')->get();
$customfields = CustomField::get();
$rows = [ ];
@ -552,8 +552,8 @@ class ReportsController extends Controller
if (e(Input::get('username')) == '1') {
// Only works if we're checked out to a user, not anything else.
if ($asset->assigneduser) {
$row[] = '"' .e($asset->assigneduser->username). '"';
if ($asset->checkedOutToUser()) {
$row[] = '"' .e($asset->assignedTo->username). '"';
} else {
$row[] = ''; // Empty string if unassigned
}
@ -561,8 +561,8 @@ class ReportsController extends Controller
if (e(Input::get('employee_num')) == '1') {
// Only works if we're checked out to a user, not anything else.
if ($asset->assigneduser) {
$row[] = '"' .e($asset->assigneduser->employee_num). '"';
if ($asset->checkedOutToUser()) {
$row[] = '"' .e($asset->assignedTo->employee_num). '"';
} else {
$row[] = ''; // Empty string if unassigned
}

View file

@ -68,8 +68,8 @@ class ViewAssetsController extends Controller
public function getRequestableIndex()
{
$assets = Asset::with('model', 'defaultLoc', 'assetloc', 'assignedTo')->Hardware()->RequestableAssets()->get();
$models = AssetModel::with('category')->RequestableModels()->get();
$assets = Asset::with('model', 'defaultLoc', 'assetloc', 'assignedTo', 'requests')->Hardware()->RequestableAssets()->get();
$models = AssetModel::with('category', 'requests', 'assets')->RequestableModels()->get();
return view('account/requestable-assets', compact('user', 'assets', 'models'));
}

View file

@ -25,7 +25,7 @@ class ActionlogsTransformer
$array = [
'id' => (int) $actionlog->id,
'icon' => $actionlog->present()->icon(),
'image' => ($actionlog->item->getImageUrl()) ? $actionlog->item->getImageUrl() : null,
'image' => (method_exists($actionlog->item, 'getImageUrl')) ? $actionlog->item->getImageUrl() : null,
'item' => ($actionlog->item) ? [
'id' => (int) $actionlog->item->id,
'name' => e($actionlog->item->getDisplayNameAttribute()),

View file

@ -38,6 +38,7 @@ class AssetMaintenancesTransformer
];
$permissions_array['available_actions'] = [
'update' => (bool) Gate::allows('update', Asset::class),
'delete' => (bool) Gate::allows('delete', Asset::class),
];

View file

@ -62,14 +62,7 @@ class AssetsTransformer
'name'=> e($asset->defaultLoc->name)
] : null,
'image' => ($asset->getImageUrl()) ? $asset->getImageUrl() : null,
'assigned_to' => ($asset->assigneduser) ? [
'id' => (int) $asset->assigneduser->id,
'username' => e($asset->assigneduser->username),
'name' => e($asset->assigneduser->getFullNameAttribute()),
'first_name'=> e($asset->assigneduser->first_name),
'last_name'=> e($asset->assigneduser->last_name),
'employee_number' => e($asset->assigneduser->employee_num),
] : null,
'assigned_to' => $this->transformAssignedTo($asset),
'warranty' => ($asset->warranty_months > 0) ? e($asset->warranty_months . ' ' . trans('admin/hardware/form.months')) : null,
'warranty_expires' => ($asset->warranty_months > 0) ? Helper::getFormattedDateObject($asset->warranty_expires, 'date') : null,
'created_at' => Helper::getFormattedDateObject($asset->created_at, 'datetime'),
@ -130,4 +123,24 @@ class AssetsTransformer
{
return (new DatatablesTransformer)->transformDatatables($assets);
}
public function transformAssignedTo($asset)
{
if ($asset->checkedOutToUser()) {
return $asset->assignedTo ? [
'id' => (int) $asset->assignedTo->id,
'username' => e($asset->assignedTo->username),
'name' => e($asset->assignedTo->getFullNameAttribute()),
'first_name'=> e($asset->assignedTo->first_name),
'last_name'=> e($asset->assignedTo->last_name),
'employee_number' => e($asset->assignedTo->employee_num),
'type' => 'user'
] : null;
}
return $asset->assignedTo ? [
'id' => $asset->assignedTo->id,
'name' => $asset->assignedTo->display_name,
'type' => $asset->assignedType()
] : null;
}
}

View file

@ -227,16 +227,14 @@ class Asset extends Depreciable
->orderBy('created_at', 'desc');
}
/**
* Even though we allow allow for checkout to things beyond users
* this method is an easy way of seeing if we are checked out to a user.
* @return mixed
*/
public function assigneduser()
public function checkedOutToUser()
{
return $this->belongsTo('\App\Models\User', 'assigned_to')
->withTrashed();
return $this->assignedType() === self::USER;
}
public function assignedTo()
@ -260,14 +258,13 @@ class Asset extends Depreciable
}
if ($this->assignedType() == self::LOCATION) {
return $this->assignedTo();
} elseif (!$this->assignedTo) {
return $this->defaultLoc();
} elseif ($this->assignedType() == self::USER) {
return $this->assignedTo->userLoc();
}
if ($this->assignedType() == self::USER) {
return $this->assignedTo->userLoc();
}
if (!$this->assignedTo) {
return $this->defaultLoc();
}
}
return $this->defaultLoc();
}
@ -529,7 +526,7 @@ class Asset extends Depreciable
/**
* Query builder scope for pending assets
* Query builder scope for searching location
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
*
@ -539,8 +536,17 @@ class Asset extends Depreciable
public function scopeAssetsByLocation($query, $location)
{
return $query->where(function ($query) use ($location) {
$query->whereHas('assigneduser', function ($query) use ($location) {
$query->where('users.location_id', '=', $location->id);
$query->whereHas('assignedTo', function ($query) use ($location) {
$query->where([
['users.location_id', '=', $location->id],
['assets.assigned_type', '=', User::class]
])->orWhere([
['locations.id', '=', $location->id],
['assets.assigned_type', '=', Location::class]
])->orWhere([
['assets.rtd_location_id', '=', $location->id],
['assets.assigned_type', '=', Asset::class]
]);
})->orWhere(function ($query) use ($location) {
$query->where('assets.rtd_location_id', '=', $location->id);
$query->whereNull('assets.assigned_to');
@ -760,18 +766,26 @@ class Asset extends Depreciable
$query->whereHas('defaultLoc', function ($query) use ($search) {
$query->where('locations.name', 'LIKE', '%'.$search.'%');
});
})->orWhere(function ($query) use ($search) {
$query->whereHas('assigneduser', function ($query) use ($search) {
$query->where(function ($query) use ($search) {
$query->where('users.first_name', 'LIKE', '%'.$search.'%')
->orWhere('users.last_name', 'LIKE', '%'.$search.'%')
->orWhere(function ($query) use ($search) {
$query->whereHas('userloc', function ($query) use ($search) {
$query->where('locations.name', 'LIKE', '%'.$search.'%');
});
});
});
});
//FIXME: This needs attention to work with checkout to not-users.
// })->orWhere(function ($query) use ($search) {
// $query->whereHas('assignedTo', function ($query) use ($search) {
// $query->where(function ($query) use ($search) {
// $query->where('assets.assigned_type', '=', User::class)
// ->join('users', 'users.id', '=', 'assets.assigned_to')
// ->where(function($query) use ($search) {
// $query->where('users.first_name', 'LIKE', '%'.$search.'%')
// ->orWhere('users.last_name', 'LIKE', '%'.$search.'%');
// });
// })->orWhere(function ($query) use ($search) {
// $query->where('assets.assigned_type', '=', Location::class)
// ->join('locations', 'locations.id', '=', 'assets.assigned_to')
// ->where('locations.name', 'LIKE', '%'.$search.'%');
// })->orWhere(function ($query) use ($search) {
// $query->where('assets.assigned_type', '=', Asset::class)
// ->join('assets as assigned_asset', 'assigned_assets.id', '=', 'assets.assigned_to')
// ->where('assigned_assets.name', 'LIKE', '%'.$search.'%');
// });
// });
})->orWhere('assets.name', 'LIKE', '%'.$search.'%')
->orWhere('assets.asset_tag', 'LIKE', '%'.$search.'%')
->orWhere('assets.serial', 'LIKE', '%'.$search.'%')
@ -1074,13 +1088,15 @@ class Asset extends Depreciable
$query->whereHas('defaultLoc', function ($query) use ($search) {
$query->where('locations.id', '=', $search);
});
})->orWhere(function ($query) use ($search) {
$query->whereHas('assigneduser', function ($query) use ($search) {
$query->whereHas('userloc', function ($query) use ($search) {
$query->where('locations.id', '=', $search);
});
});
});
// FIXME: This needs porting to checkout to non-user.
// ->orWhere(function ($query) use ($search) {
// $query->whereHas('assigneduser', function ($query) use ($search) {
// $query->whereHas('userloc', function ($query) use ($search) {
// $query->where('locations.id', '=', $search);
// });
// });
// });
}

View file

@ -73,7 +73,7 @@ class Consumable extends SnipeModel
return $this->belongsTo('\App\Models\User', 'user_id');
}
public function consumableAssigments()
public function consumableAssignments()
{
return $this->hasMany('\App\Models\ConsumableAssignment');
}

View file

@ -19,9 +19,9 @@ trait Requestable
public function isRequestedBy(User $user)
{
return $this->requests()
->where('user_id', $user->id)
->exists();
$requests = $this->requests->where('user_id', $user->id);
return $requests->count() > 0;
}
public function scopeRequestedBy($query, User $user)

View file

@ -82,4 +82,8 @@ class SnipeModel extends Model
{
return $this->name;
}
public function name() {
return $this->name;
}
}

View file

@ -98,7 +98,7 @@ class AssetPresenter extends Presenter
"sortable" => true,
"title" => trans('admin/hardware/form.checkedout_to'),
"visible" => true,
"formatter" => "usersLinkObjFormatter"
"formatter" => "polymorphicItemFormatter"
], [
"field" => "employee_number",
"searchable" => false,

View file

@ -7,7 +7,7 @@ return array(
'asset' => 'Asset',
'bulk_checkout' => 'Checkout Assets to User',
'checkin' => 'Checkin Asset',
'checkout' => 'Checkout Asset to User',
'checkout' => 'Checkout Asset',
'clone' => 'Clone Asset',
'deployable' => 'Deployable',
'deleted' => 'This asset has been deleted. <a href="/hardware/:asset_id/restore">Click here to restore it</a>.',

View file

@ -116,7 +116,7 @@
>
{{ csrf_field() }}
<td>{{$requestableModel->name}}</td>
<td>{{$requestableModel->assets()->where('requestable', '1')->count()}}</td>
<td>{{$requestableModel->assets->where('requestable', '1')->count()}}</td>
<td><input type="text" name="request-quantity" value=""></td>
<td>
@if ($requestableModel->isRequestedBy(Auth::user()))

View file

@ -60,15 +60,21 @@
@include ('partials.bootstrap-table', ['exportFile' => 'maintenances-export', 'search' => true])
<script>
function maintenanceActions(value, row) {
var actions = '<nobr>';
if ((row) && (row.available_actions.update === true)) {
actions += '<a href="{{ url('/') }}/hardware/maintenances/' + row.id + '/edit" class="btn btn-sm btn-warning" data-tooltip="true" title="Update"><i class="fa fa-pencil"></i></a>&nbsp;';
}
actions += '</nobr>'
if ((row) && (row.available_actions.delete === true)) {
return '<a href="{{ url('/') }}/hardware/maintenances/' + row.id + '" '
actions += '<a href="{{ url('/') }}/hardware/maintenances/' + row.id + '" '
+ ' class="btn btn-danger btn-sm delete-asset" data-tooltip="true" '
+ ' data-toggle="modal" '
+ ' data-content="{{ trans('general.sure_to_delete') }} ' + row.name + '?" '
+ ' data-title="{{ trans('general.delete') }}" onClick="return false;">'
+ '<i class="fa fa-trash"></i></a></nobr>';
}
return actions;
}
</script>

View file

@ -35,7 +35,7 @@
name="consumable_users"
class="table table-striped snipe-table"
id="table"
data-url="{{route('api.consumables.show', $consumable->id)}}"
data-url="{{route('api.consumables.showUsers', $consumable->id)}}"
data-cookie="true"
data-click-to-select="true"
data-cookie-id-table="consumableDetailTable-{{ config('version.hash_version') }}"

View file

@ -48,7 +48,7 @@
</td>
<td>
@if ($asset->assignedTo)
{{ $asset->assignedTo->present()->name().' ' .$asset->assigneduser ? '('.$asset->assigneduser->username. ')' : ''}}
{{ $asset->assignedTo->present()->name()}}
@endif
</td>
</tr>

View file

@ -334,12 +334,12 @@
</ul>
@endif
@if (($asset->assigneduser) && ($asset->assigned_to > 0) && ($asset->deleted_at==''))
@if (($asset->checkedOutToUser()) && ($asset->assigned_to > 0) && ($asset->deleted_at==''))
{{-- @TODO This should be extnded for details about non users --}}
<h6><br>{{ trans('admin/hardware/form.checkedout_to') }}</h6>
<ul>
<li>
<img src="{{ $asset->assigneduser->present()->gravatar() }}" class="img-circle" style="width: 100px; margin-right: 20px;" /><br /><br />
<img src="{{ $asset->assignedTo->present()->gravatar() }}" class="img-circle" style="width: 100px; margin-right: 20px;" /><br /><br />
</li>
<li>
{{ $asset->assignedTo->present()->nameUrl() }}
@ -357,12 +357,12 @@
@endif
@endif
@if (isset($asset->assigneduser->email))
<li><br /><i class="fa fa-envelope-o"></i> <a href="mailto:{{ $asset->assigneduser->email }}">{{ $asset->assigneduser->email }}</a></li>
@if (isset($asset->assignedTo->email))
<li><br /><i class="fa fa-envelope-o"></i> <a href="mailto:{{ $asset->assignedTo->email }}">{{ $asset->assignedTo->email }}</a></li>
@endif
@if ((isset($asset->assigneduser->phone)) && ($asset->assigneduser->phone!=''))
<li><i class="fa fa-phone"></i> {{ $asset->assigneduser->phone }}</li>
@if ((isset($asset->assignedTo->phone)) && ($asset->assignedTo->phone!=''))
<li><i class="fa fa-phone"></i> {{ $asset->assignedTo->phone }}</li>
@endif
</ul>
@endif

View file

@ -401,19 +401,19 @@
@if (($asset->assignedTo) && ($asset->deleted_at==''))
<h4>{{ trans('admin/hardware/form.checkedout_to') }}</h4>
<p>
@if($asset->assigned_type == User::class) <!-- Only users have avatars currently-->
<img src="{{ $asset->assignedTo->present()->gravatar() }}" class="user-image-inline" alt="{{ $asset->assigneduser->present()->fullName() }}">
@if($asset->checkedOutToUser()) <!-- Only users have avatars currently-->
<img src="{{ $asset->assignedTo->present()->gravatar() }}" class="user-image-inline" alt="{{ $asset->assignedTo->present()->fullName() }}">
@endif
{!! $asset->assignedTo->present()->glyph() . ' ' .$asset->assignedTo->present()->nameUrl() !!}
</p>
<ul class="list-unstyled">
@if ((isset($asset->assigneduser->email)) && ($asset->assigneduser->email!=''))
<li><i class="fa fa-envelope-o"></i> <a href="mailto:{{ $asset->assigneduser->email }}">{{ $asset->assigneduser->email }}</a></li>
@if ((isset($asset->assignedTo->email)) && ($asset->assignedTo->email!=''))
<li><i class="fa fa-envelope-o"></i> <a href="mailto:{{ $asset->assignedTo->email }}">{{ $asset->assignedTo->email }}</a></li>
@endif
@if ((isset($asset->assigneduser->phone)) && ($asset->assigneduser->phone!=''))
<li><i class="fa fa-phone"></i> {{ $asset->assigneduser->phone }}</li>
@if ((isset($asset->assignedTo->phone)) && ($asset->assignedTo->phone!=''))
<li><i class="fa fa-phone"></i> {{ $asset->assignedTo->phone }}</li>
@endif
@if (isset($asset->assetLoc))
@ -661,7 +661,7 @@
</td>
<td>
@if ( \App\Helpers\Helper::checkUploadIsImage($file->get_src('assets')))
<a href="../{{ $asset->id }}/showfile/{{ $file->id }}" data-toggle="lightbox" data-type="image"><img src="../{{ $asset->id }}/showfile/{{ $file->id }}"" class="img-thumbnail" style="max-width: 50px;"></a>
<a href="{{ route('show/assetfile', ['assetId' => $asset->id, 'fileId' =>$file->id]) }}" data-toggle="lightbox" data-type="image"><img src="{{ route('show/assetfile', ['assetId' => $asset->id, 'fileId' =>$file->id]) }}" class="img-thumbnail" style="max-width: 50px;"></a>
@endif
</td>
<td>

View file

@ -257,7 +257,7 @@
@for($i=0; count($alert_items) > $i; $i++)
<li><!-- Task item -->
<a href="{{ url('/') }}/{{ $alert_items[$i]['type'] }}/{{ $alert_items[$i]['id'] }}/view">
<a href="{{route($alert_items[$i]['type'].'.show', $alert_items[$i]['id'])}}">
<h3>{{ $alert_items[$i]['name'] }}
<small class="pull-right">
{{ $alert_items[$i]['remaining'] }} remaining

View file

@ -55,7 +55,7 @@
<th data-sortable="true" data-field="name" data-searchable="true" data-formatter="hardwareLinkFormatter">{{ trans('general.name') }}</th>
<th data-sortable="true" data-field="asset_tag" data-formatter="hardwareLinkFormatter">{{ trans('general.asset_tag') }}</th>
<th data-sortable="true" data-field="serial" data-formatter="hardwareLinkFormatter">{{ trans('admin/hardware/table.serial') }}</th>
<th data-sortable="false" data-field="assigned_to" data-formatter="usersLinkObjFormatter">{{ trans('general.user') }}</th>
<th data-sortable="false" data-field="assigned_to" data-formatter="polymorphicItemFormatter">{{ trans('general.user') }}</th>
<th data-sortable="false" data-field="inout" data-formatter="hardwareInOutFormatter">{{ trans('admin/hardware/table.change') }}</th>
<th data-switchable="false" data-searchable="false" data-sortable="false" data-field="actions" data-formatter="hardwareActionsFormatter">{{ trans('table.actions') }}</th>
</tr>

View file

@ -192,6 +192,8 @@ $('.snipe-table').bootstrapTable({
item_destination = 'licenses';
} else if (value.type == 'user') {
item_destination = 'users';
} else if (value.type == 'location') {
item_destination = 'locations'
}
return '<a href="{{ url('/') }}/' + item_destination +'/' + value.id + '"> ' + value.name + '</a>';

View file

@ -52,7 +52,7 @@
@endif
</td>
<td>
@if (($asset->assignedTo) && ($asset->assigneduser->assetLoc))
@if (($asset->checkedOutToUser()) && ($asset->assignedTo->assetLoc))
{{ $asset->assignedTo->assetLoc->city }}, {{ $asset->assignedTo->assetLoc->state}}
@endif
</td>

View file

@ -49,18 +49,18 @@
@foreach ($supplier->assets as $supplierassets)
<tr>
<td>
<a href="{{ route('suppliers.show', $supplierassets->id) }}">
<a href="{{ route('hardware.show', $supplierassets->id) }}">
{{ $supplierassets->asset_tag }}
</a>
</td>
<td>
<a href="{{ route('suppliers.show', $supplierassets->id) }}">
<a href="{{ route('hardware.show', $supplierassets->id) }}">
{{ $supplierassets->name }}
</a>
</td>
<td>
@if ($supplierassets->assigneduser)
{!! $supplierassets->assigneduser->present()->nameUrl() !!}
@if ($supplierassets->assignedTo)
{!! $supplierassets->assignedTo->present()->nameUrl() !!}
@endif
</td>
<td>

View file

@ -141,7 +141,12 @@ Route::group(['prefix' => 'v1','namespace' => 'Api'], function () {
'parameters' => ['consumable' => 'consumable_id']
]
); // Consumables resource
Route::get('consumables/view/{id}/users',
[
'as' => 'api.consumables.showUsers',
'uses' => 'ConsumablesController@getDataView'
]
);
/*--- Depreciations API ---*/

View file

@ -92,13 +92,16 @@ Route::group(
'uses' => 'AssetsController@postUpload'
]);
Route::get('{assetId}/showfile/{fileId}', [
'as' => 'show/assetfile',
'uses' => 'AssetsController@displayFile'
]);
Route::delete('{assetId}/showfile/{fileId}/delete', [
'as' => 'delete/assetfile',
'uses' => 'AssetsController@deleteFile'
]);
Route::post(
'bulkedit',