Last active
October 16, 2019 10:23
-
-
Save chay22/761f7e22da0536c341284e632476cc83 to your computer and use it in GitHub Desktop.
Snipe-IT bootstrap-table upgrade
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Models; | |
use App\Exceptions\CheckoutNotAllowed; | |
use App\Http\Traits\UniqueSerialTrait; | |
use App\Http\Traits\UniqueUndeletedTrait; | |
use App\Models\Traits\Searchable; | |
use App\Presenters\Presentable; | |
use AssetPresenter; | |
use Auth; | |
use Carbon\Carbon; | |
use Config; | |
use Illuminate\Database\Eloquent\Builder; | |
use Illuminate\Database\Eloquent\SoftDeletes; | |
use Log; | |
use Watson\Validating\ValidatingTrait; | |
use DB; | |
use App\Notifications\CheckinAssetNotification; | |
use App\Notifications\CheckoutAssetNotification; | |
/** | |
* Model for Assets. | |
* | |
* @version v1.0 | |
*/ | |
class Asset extends Depreciable | |
{ | |
protected $presenter = 'App\Presenters\AssetPresenter'; | |
use Loggable, Requestable, Presentable, SoftDeletes, ValidatingTrait, UniqueUndeletedTrait, UniqueSerialTrait; | |
const LOCATION = 'location'; | |
const ASSET = 'asset'; | |
const USER = 'user'; | |
const ACCEPTANCE_PENDING = 'pending'; | |
/** | |
* Set static properties to determine which checkout/checkin handlers we should use | |
*/ | |
public static $checkoutClass = CheckoutAssetNotification::class; | |
public static $checkinClass = CheckinAssetNotification::class; | |
/** | |
* The database table used by the model. | |
* | |
* @var string | |
*/ | |
protected $table = 'assets'; | |
/** | |
* Whether the model should inject it's identifier to the unique | |
* validation rules before attempting validation. If this property | |
* is not set in the model it will default to true. | |
* | |
* @var boolean | |
*/ | |
protected $injectUniqueIdentifier = true; | |
// We set these as protected dates so that they will be easily accessible via Carbon | |
protected $dates = [ | |
'created_at', | |
'updated_at', | |
'deleted_at', | |
'purchase_date', | |
'last_checkout', | |
'expected_checkin', | |
'last_audit_date', | |
'next_audit_date' | |
]; | |
protected $rules = [ | |
'name' => 'max:255|nullable', | |
'model_id' => 'required|integer|exists:models,id', | |
'status_id' => 'required|integer|exists:status_labels,id', | |
'company_id' => 'integer|nullable', | |
'warranty_months' => 'numeric|nullable|digits_between:0,240', | |
'physical' => 'numeric|max:1|nullable', | |
'checkout_date' => 'date|max:10|min:10|nullable', | |
'checkin_date' => 'date|max:10|min:10|nullable', | |
'supplier_id' => 'numeric|nullable', | |
'asset_tag' => 'required|min:1|max:255|unique_undeleted', | |
'status' => 'integer', | |
'serial' => 'unique_serial|nullable', | |
'purchase_cost' => 'numeric|nullable', | |
'next_audit_date' => 'date|nullable', | |
'last_audit_date' => 'date|nullable', | |
]; | |
/** | |
* The attributes that are mass assignable. | |
* | |
* @var array | |
*/ | |
protected $fillable = [ | |
'asset_tag', | |
'assigned_to', | |
'assigned_type', | |
'company_id', | |
'image', | |
'location_id', | |
'model_id', | |
'name', | |
'notes', | |
'order_number', | |
'purchase_cost', | |
'purchase_date', | |
'rtd_location_id', | |
'serial', | |
'status_id', | |
'supplier_id', | |
'warranty_months', | |
]; | |
use Searchable; | |
/** | |
* The attributes that should be included when searching the model. | |
* | |
* @var array | |
*/ | |
protected $searchableAttributes = [ | |
'name', | |
'asset_tag', | |
'serial', | |
'order_number', | |
'purchase_cost', | |
'notes', | |
'created_at', | |
'updated_at', | |
'purchase_date', | |
'expected_checkin', | |
'next_audit_date', | |
'last_audit_date' | |
]; | |
/** | |
* The relations and their attributes that should be included when searching the model. | |
* | |
* @var array | |
*/ | |
protected $searchableRelations = [ | |
'assetstatus' => ['name'], | |
'supplier' => ['name'], | |
'company' => ['name'], | |
'defaultLoc' => ['name'], | |
'model' => ['name', 'model_number'], | |
'model.category' => ['name'], | |
'model.manufacturer' => ['name'], | |
]; | |
public function getDisplayNameAttribute() | |
{ | |
return $this->present()->name(); | |
} | |
/** | |
* Returns the warranty expiration date as Carbon object | |
* @return \Carbon|null | |
*/ | |
public function getWarrantyExpiresAttribute() | |
{ | |
if (isset($this->attributes['warranty_months']) && isset($this->attributes['purchase_date'])) { | |
if (is_string($this->attributes['purchase_date']) || is_string($this->attributes['purchase_date'])) { | |
$purchase_date = \Carbon\Carbon::parse($this->attributes['purchase_date']); | |
} else { | |
$purchase_date = \Carbon\Carbon::instance($this->attributes['purchase_date']); | |
} | |
$purchase_date->setTime(0, 0, 0); | |
return $purchase_date->addMonths((int) $this->attributes['warranty_months']); | |
} | |
return null; | |
} | |
public function company() | |
{ | |
return $this->belongsTo('\App\Models\Company', 'company_id'); | |
} | |
public function availableForCheckout() | |
{ | |
if ( | |
(empty($this->assigned_to)) && | |
(empty($this->deleted_at)) && | |
(($this->assetstatus) && ($this->assetstatus->deployable == 1))) | |
{ | |
return true; | |
} | |
return false; | |
} | |
/** | |
* Checkout asset | |
* @param User $user | |
* @param User $admin | |
* @param Carbon $checkout_at | |
* @param Carbon $expected_checkin | |
* @param string $note | |
* @param null $name | |
* @return bool | |
*/ | |
//FIXME: The admin parameter is never used. Can probably be removed. | |
public function checkOut($target, $admin = null, $checkout_at = null, $expected_checkin = null, $note = null, $name = null, $location = null) | |
{ | |
if (!$target) { | |
return false; | |
} | |
if ($expected_checkin) { | |
$this->expected_checkin = $expected_checkin; | |
} | |
$this->last_checkout = $checkout_at; | |
$this->assignedTo()->associate($target); | |
if ($name != null) { | |
$this->name = $name; | |
} | |
if ($location != null) { | |
$this->location_id = $location; | |
} else { | |
if($target->location) { | |
$this->location_id = $target->location->id; | |
} | |
if($target instanceof Location) { | |
$this->location_id = $target->id; | |
} | |
} | |
/** | |
* Does the user have to confirm that they accept the asset? | |
* | |
* If so, set the acceptance-status to "pending". | |
* This value is used in the unaccepted assets reports, for example | |
* | |
* @see https://github.com/snipe/snipe-it/issues/5772 | |
*/ | |
if ($this->requireAcceptance() && $target instanceof User) { | |
$this->accepted = self::ACCEPTANCE_PENDING; | |
} | |
if ($this->save()) { | |
$this->logCheckout($note, $target); | |
$this->increment('checkout_counter', 1); | |
return true; | |
} | |
return false; | |
} | |
public function getDetailedNameAttribute() | |
{ | |
if ($this->assignedto) { | |
$user_name = $this->assignedto->present()->name(); | |
} else { | |
$user_name = "Unassigned"; | |
} | |
return $this->asset_tag . ' - ' . $this->name . ' (' . $user_name . ') ' . ($this->model) ? $this->model->name: ''; | |
} | |
public function validationRules($id = '0') | |
{ | |
return $this->rules; | |
} | |
/** | |
* Set depreciation relationship | |
*/ | |
public function depreciation() | |
{ | |
return $this->model->belongsTo('\App\Models\Depreciation', 'depreciation_id'); | |
} | |
/** | |
* Get components assigned to this asset | |
*/ | |
public function components() | |
{ | |
return $this->belongsToMany('\App\Models\Component', 'components_assets', 'asset_id', 'component_id')->withPivot('id', 'assigned_qty')->withTrashed(); | |
} | |
/** | |
* Get depreciation attribute from associated asset model | |
*/ | |
public function get_depreciation() | |
{ | |
if (($this->model) && ($this->model->depreciation)) { | |
return $this->model->depreciation; | |
} | |
} | |
/** | |
* Get uploads for this asset | |
*/ | |
public function uploads() | |
{ | |
return $this->hasMany('\App\Models\Actionlog', 'item_id') | |
->where('item_type', '=', Asset::class) | |
->where('action_type', '=', 'uploaded') | |
->whereNotNull('filename') | |
->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 checkedOutToUser() | |
{ | |
return $this->assignedType() === self::USER; | |
} | |
public function assignedTo() | |
{ | |
return $this->morphTo('assigned', 'assigned_type', 'assigned_to'); | |
} | |
public function assignedAssets() | |
{ | |
return $this->morphMany('App\Models\Asset', 'assigned', 'assigned_type', 'assigned_to')->withTrashed(); | |
} | |
/** | |
* Get the asset's location based on the assigned user | |
**/ | |
public function assetLoc($iterations = 1,$first_asset = null) | |
{ | |
if (!empty($this->assignedType())) { | |
if ($this->assignedType() == self::ASSET) { | |
if(!$first_asset) { | |
$first_asset=$this; | |
} | |
if($iterations>10) { | |
throw new \Exception("Asset assignment Loop for Asset ID: ".$first_asset->id); | |
} | |
$assigned_to=Asset::find($this->assigned_to); //have to do this this way because otherwise it errors | |
if ($assigned_to) { | |
return $assigned_to->assetLoc($iterations + 1, $first_asset); | |
} // Recurse until we have a final location | |
} | |
if ($this->assignedType() == self::LOCATION) { | |
if ($this->assignedTo) { | |
return $this->assignedTo; | |
} | |
} | |
if ($this->assignedType() == self::USER) { | |
if (($this->assignedTo) && $this->assignedTo->userLoc) { | |
return $this->assignedTo->userLoc; | |
} | |
//this makes no sense | |
return $this->defaultLoc; | |
} | |
} | |
return $this->defaultLoc; | |
} | |
public function assignedType() | |
{ | |
return strtolower(class_basename($this->assigned_type)); | |
} | |
/** | |
* Get the asset's location based on default RTD location | |
**/ | |
public function defaultLoc() | |
{ | |
return $this->belongsTo('\App\Models\Location', 'rtd_location_id'); | |
} | |
public function getImageUrl() | |
{ | |
if ($this->image && !empty($this->image)) { | |
return url('/').'/uploads/assets/'.$this->image; | |
} elseif ($this->model && !empty($this->model->image)) { | |
return url('/').'/uploads/models/'.$this->model->image; | |
} | |
return false; | |
} | |
/** | |
* Get action logs for this asset | |
*/ | |
public function assetlog() | |
{ | |
return $this->hasMany('\App\Models\Actionlog', 'item_id') | |
->where('item_type', '=', Asset::class) | |
->orderBy('created_at', 'desc') | |
->withTrashed(); | |
} | |
/** | |
* Get checkouts | |
*/ | |
public function checkouts() | |
{ | |
return $this->assetlog()->where('action_type', '=', 'checkout') | |
->orderBy('created_at', 'desc') | |
->withTrashed(); | |
} | |
/** | |
* Get checkins | |
*/ | |
public function checkins() | |
{ | |
return $this->assetlog() | |
->where('action_type', '=', 'checkin from') | |
->orderBy('created_at', 'desc') | |
->withTrashed(); | |
} | |
/** | |
* Get user requests | |
*/ | |
public function userRequests() | |
{ | |
return $this->assetlog() | |
->where('action_type', '=', 'requested') | |
->orderBy('created_at', 'desc') | |
->withTrashed(); | |
} | |
/** | |
* assetmaintenances | |
* Get improvements for this asset | |
* | |
* @return mixed | |
* @author Vincent Sposato <[email protected]> | |
* @version v1.0 | |
*/ | |
public function assetmaintenances() | |
{ | |
return $this->hasMany('\App\Models\AssetMaintenance', 'asset_id') | |
->orderBy('created_at', 'desc'); | |
} | |
/** | |
* Get action logs for this asset | |
*/ | |
public function adminuser() | |
{ | |
return $this->belongsTo('\App\Models\User', 'user_id'); | |
} | |
/** | |
* Get total assets | |
*/ | |
public static function assetcount() | |
{ | |
return Company::scopeCompanyables(Asset::where('physical', '=', '1')) | |
->whereNull('deleted_at', 'and') | |
->count(); | |
} | |
/** | |
* Get total assets not checked out | |
*/ | |
public static function availassetcount() | |
{ | |
return Asset::RTD() | |
->whereNull('deleted_at') | |
->count(); | |
} | |
/** | |
* Get requestable assets | |
*/ | |
public static function getRequestable() | |
{ | |
return Asset::Requestable() | |
->whereNull('deleted_at') | |
->count(); | |
} | |
/** | |
* Get asset status | |
*/ | |
public function assetstatus() | |
{ | |
return $this->belongsTo('\App\Models\Statuslabel', 'status_id'); | |
} | |
public function model() | |
{ | |
return $this->belongsTo('\App\Models\AssetModel', 'model_id')->withTrashed(); | |
} | |
public static function getExpiringWarrantee($days = 30) | |
{ | |
return Asset::where('archived', '=', '0') | |
->whereNotNull('warranty_months') | |
->whereNotNull('purchase_date') | |
->whereNull('deleted_at') | |
->whereRaw(\DB::raw('DATE_ADD(`purchase_date`,INTERVAL `warranty_months` MONTH) <= DATE(NOW() + INTERVAL ' | |
. $days | |
. ' DAY) AND DATE_ADD(`purchase_date`,INTERVAL `warranty_months` MONTH) > NOW()')) | |
->orderBy('purchase_date', 'ASC') | |
->get(); | |
} | |
/** | |
* Get the license seat information | |
**/ | |
public function licenses() | |
{ | |
return $this->belongsToMany('\App\Models\License', 'license_seats', 'asset_id', 'license_id'); | |
} | |
public function licenseseats() | |
{ | |
return $this->hasMany('\App\Models\LicenseSeat', 'asset_id'); | |
} | |
public function supplier() | |
{ | |
return $this->belongsTo('\App\Models\Supplier', 'supplier_id'); | |
} | |
public function location() | |
{ | |
return $this->belongsTo('\App\Models\Location', 'location_id'); | |
} | |
/** | |
* Get auto-increment | |
*/ | |
public static function autoincrement_asset() | |
{ | |
$settings = \App\Models\Setting::getSettings(); | |
if ($settings->auto_increment_assets == '1') { | |
$temp_asset_tag = \DB::table('assets') | |
->where('physical', '=', '1') | |
->max('asset_tag'); | |
$asset_tag_digits = preg_replace('/\D/', '', $temp_asset_tag); | |
$asset_tag = preg_replace('/^0*/', '', $asset_tag_digits); | |
if ($settings->zerofill_count > 0) { | |
return $settings->auto_increment_prefix.Asset::zerofill($settings->next_auto_tag_base, $settings->zerofill_count); | |
} | |
return $settings->auto_increment_prefix.$settings->next_auto_tag_base; | |
} else { | |
return false; | |
} | |
} | |
/* | |
* Get the next base number for the auto-incrementer. We'll add the zerofill and | |
* prefixes on the fly as we generate the number | |
* | |
*/ | |
public static function nextAutoIncrement($assets) | |
{ | |
$max = 1; | |
foreach ($assets as $asset) { | |
$results = preg_match ( "/\d+$/" , $asset['asset_tag'], $matches); | |
if ($results) | |
{ | |
$number = $matches[0]; | |
if ($number > $max) | |
{ | |
$max = $number; | |
} | |
} | |
} | |
return $max + 1; | |
} | |
public static function zerofill($num, $zerofill = 3) | |
{ | |
return str_pad($num, $zerofill, '0', STR_PAD_LEFT); | |
} | |
public function checkin_email() | |
{ | |
return $this->model->category->checkin_email; | |
} | |
public function requireAcceptance() | |
{ | |
return $this->model->category->require_acceptance; | |
} | |
public function getEula() | |
{ | |
$Parsedown = new \Parsedown(); | |
if ($this->model->category->eula_text) { | |
return $Parsedown->text(e($this->model->category->eula_text)); | |
} elseif ($this->model->category->use_default_eula == '1') { | |
return $Parsedown->text(e(Setting::getSettings()->default_eula_text)); | |
} else { | |
return false; | |
} | |
} | |
/** | |
* Run additional, advanced searches. | |
* | |
* @param Illuminate\Database\Eloquent\Builder $query | |
* @param array $terms The search terms | |
* @return Illuminate\Database\Eloquent\Builder | |
*/ | |
public function advancedTextSearch(Builder $query, array $terms) { | |
/** | |
* Assigned user | |
*/ | |
$query = $query->leftJoin('users as assets_users',function ($leftJoin) { | |
$leftJoin->on("assets_users.id", "=", "assets.assigned_to") | |
->where("assets.assigned_type", "=", User::class); | |
}); | |
foreach($terms as $term) { | |
$query = $query | |
->orWhere('assets_users.first_name', 'LIKE', '%'.$term.'%') | |
->orWhere('assets_users.last_name', 'LIKE', '%'.$term.'%') | |
->orWhere('assets_users.username', 'LIKE', '%'.$term.'%') | |
->orWhereRaw('CONCAT('.DB::getTablePrefix().'assets_users.first_name," ",'.DB::getTablePrefix().'assets_users.last_name) LIKE ?', ["%$term%", "%$term%"]); | |
} | |
/** | |
* Assigned location | |
*/ | |
$query = $query->leftJoin('locations as assets_locations',function ($leftJoin) { | |
$leftJoin->on("assets_locations.id","=","assets.assigned_to") | |
->where("assets.assigned_type","=",Location::class); | |
}); | |
foreach($terms as $term) { | |
$query = $query->orWhere('assets_locations.name', 'LIKE', '%'.$term.'%'); | |
} | |
/** | |
* Assigned assets | |
*/ | |
$query = $query->leftJoin('assets as assigned_assets',function ($leftJoin) { | |
$leftJoin->on('assigned_assets.id', '=', 'assets.assigned_to') | |
->where('assets.assigned_type', '=', Asset::class); | |
}); | |
foreach($terms as $term) { | |
$query = $query->orWhere('assigned_assets.name', 'LIKE', '%'.$term.'%'); | |
} | |
return $query; | |
} | |
/** | |
* ----------------------------------------------- | |
* BEGIN QUERY SCOPES | |
* ----------------------------------------------- | |
**/ | |
/** | |
* Query builder scope for hardware | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeHardware($query) | |
{ | |
return $query->where('physical', '=', '1'); | |
} | |
/** | |
* Query builder scope for pending assets | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopePending($query) | |
{ | |
return $query->whereHas('assetstatus', function ($query) { | |
$query->where('deployable', '=', 0) | |
->where('pending', '=', 1) | |
->where('archived', '=', 0); | |
}); | |
} | |
/** | |
* Query builder scope for searching location | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeAssetsByLocation($query, $location) | |
{ | |
return $query->where(function ($query) use ($location) { | |
$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'); | |
}); | |
}); | |
} | |
/** | |
* Query builder scope for RTD assets | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeRTD($query) | |
{ | |
return $query->whereNULL('assets.assigned_to') | |
->whereHas('assetstatus', function ($query) { | |
$query->where('deployable', '=', 1) | |
->where('pending', '=', 0) | |
->where('archived', '=', 0); | |
}); | |
} | |
/** | |
* Query builder scope for Undeployable assets | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeUndeployable($query) | |
{ | |
return $query->whereHas('assetstatus', function ($query) { | |
$query->where('deployable', '=', 0) | |
->where('pending', '=', 0) | |
->where('archived', '=', 0); | |
}); | |
} | |
/** | |
* Query builder scope for non-Archived assets | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeNotArchived($query) | |
{ | |
return $query->whereHas('assetstatus', function ($query) { | |
$query->where('archived', '=', 0); | |
}); | |
} | |
/** | |
* Query builder scope for Assets that are due for auditing, based on the assets.next_audit_date | |
* and settings.audit_warning_days. | |
* | |
* This is/will be used in the artisan command snipeit:upcoming-audits and also | |
* for an upcoming API call for retrieving a report on assets that will need to be audited. | |
* | |
* Due for audit soon: | |
* next_audit_date greater than or equal to now (must be in the future) | |
* and (next_audit_date - threshold days) <= now () | |
* | |
* Example: | |
* next_audit_date = May 4, 2025 | |
* threshold for alerts = 30 days | |
* now = May 4, 2019 | |
* | |
* @author A. Gianotto <[email protected]> | |
* @since v4.6.16 | |
* @param Setting $settings | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeDueForAudit($query, $settings) | |
{ | |
return $query->whereNotNull('assets.next_audit_date') | |
->where('assets.next_audit_date', '>=', Carbon::now()) | |
->whereRaw("DATE_SUB(assets.next_audit_date, INTERVAL $settings->audit_warning_days DAY) <= '".Carbon::now()."'") | |
->where('assets.archived', '=', 0) | |
->NotArchived(); | |
} | |
/** | |
* Query builder scope for Assets that are OVERDUE for auditing, based on the assets.next_audit_date | |
* and settings.audit_warning_days. It checks to see if assets.next audit_date is before now | |
* | |
* This is/will be used in the artisan command snipeit:upcoming-audits and also | |
* for an upcoming API call for retrieving a report on overdue assets. | |
* | |
* @author A. Gianotto <[email protected]> | |
* @since v4.6.16 | |
* @param Setting $settings | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeOverdueForAudit($query) | |
{ | |
return $query->whereNotNull('assets.next_audit_date') | |
->where('assets.next_audit_date', '<', Carbon::now()) | |
->where('assets.archived', '=', 0) | |
->NotArchived(); | |
} | |
/** | |
* Query builder scope for Assets that are due for auditing OR overdue, based on the assets.next_audit_date | |
* and settings.audit_warning_days. | |
* | |
* This is/will be used in the artisan command snipeit:upcoming-audits and also | |
* for an upcoming API call for retrieving a report on assets that will need to be audited. | |
* | |
* @author A. Gianotto <[email protected]> | |
* @since v4.6.16 | |
* @param Setting $settings | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeDueOrOverdueForAudit($query, $settings) | |
{ | |
$interval = $settings->audit_warning_days ?? 0; | |
return $query->whereNotNull('assets.next_audit_date') | |
->whereRaw("DATE_SUB(assets.next_audit_date, INTERVAL $interval DAY) <= '".Carbon::now()."'") | |
->where('assets.archived', '=', 0) | |
->NotArchived(); | |
} | |
/** | |
* Query builder scope for Archived assets | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeArchived($query) | |
{ | |
return $query->whereHas('assetstatus', function ($query) { | |
$query->where('deployable', '=', 0) | |
->where('pending', '=', 0) | |
->where('archived', '=', 1); | |
}); | |
} | |
/** | |
* Query builder scope for Deployed assets | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeDeployed($query) | |
{ | |
return $query->where('assigned_to', '>', '0'); | |
} | |
/** | |
* Query builder scope for Requestable assets | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeRequestableAssets($query) | |
{ | |
return Company::scopeCompanyables($query->where('requestable', '=', 1)) | |
->whereHas('assetstatus', function ($query) { | |
$query->where('deployable', '=', 1) | |
->where('pending', '=', 0) | |
->where('archived', '=', 0); | |
}); | |
} | |
/** | |
* Query builder scope for Deleted assets | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeDeleted($query) | |
{ | |
return $query->whereNotNull('assets.deleted_at'); | |
} | |
/** | |
* scopeInModelList | |
* Get all assets in the provided listing of model ids | |
* | |
* @param $query | |
* @param array $modelIdListing | |
* | |
* @return mixed | |
* @author Vincent Sposato <[email protected]> | |
* @version v1.0 | |
*/ | |
public function scopeInModelList($query, array $modelIdListing) | |
{ | |
return $query->whereIn('assets.model_id', $modelIdListing); | |
} | |
/** | |
* Query builder scope to get not-yet-accepted assets | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeNotYetAccepted($query) | |
{ | |
return $query->where("accepted", "=", "pending"); | |
} | |
/** | |
* Query builder scope to get rejected assets | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeRejected($query) | |
{ | |
return $query->where("accepted", "=", "rejected"); | |
} | |
/** | |
* Query builder scope to get accepted assets | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeAccepted($query) | |
{ | |
return $query->where("accepted", "=", "accepted"); | |
} | |
/** | |
* Query builder scope to search on text for complex Bootstrap Tables API. | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* @param text $search Search term | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeAssignedSearch($query, $search) | |
{ | |
$search = explode(' OR ', $search); | |
return $query->leftJoin('users as assets_users',function ($leftJoin) { | |
$leftJoin->on("assets_users.id", "=", "assets.assigned_to") | |
->where("assets.assigned_type", "=", User::class); | |
})->leftJoin('locations as assets_locations',function ($leftJoin) { | |
$leftJoin->on("assets_locations.id","=","assets.assigned_to") | |
->where("assets.assigned_type","=",Location::class); | |
})->leftJoin('assets as assigned_assets',function ($leftJoin) { | |
$leftJoin->on('assigned_assets.id', '=', 'assets.assigned_to') | |
->where('assets.assigned_type', '=', Asset::class); | |
})->where(function ($query) use ($search) { | |
foreach ($search as $search) { | |
$query->whereHas('model', function ($query) use ($search) { | |
$query->whereHas('category', function ($query) use ($search) { | |
$query->where(function ($query) use ($search) { | |
$query->where('categories.name', 'LIKE', '%'.$search.'%') | |
->orWhere('models.name', 'LIKE', '%'.$search.'%') | |
->orWhere('models.model_number', 'LIKE', '%'.$search.'%'); | |
}); | |
}); | |
})->orWhereHas('model', function ($query) use ($search) { | |
$query->whereHas('manufacturer', function ($query) use ($search) { | |
$query->where(function ($query) use ($search) { | |
$query->where('manufacturers.name', 'LIKE', '%'.$search.'%'); | |
}); | |
}); | |
})->orWhere(function ($query) use ($search) { | |
$query->where('assets_users.first_name', 'LIKE', '%'.$search.'%') | |
->orWhere('assets_users.last_name', 'LIKE', '%'.$search.'%') | |
->orWhereRaw('CONCAT('.DB::getTablePrefix().'assets_users.first_name," ",'.DB::getTablePrefix().'assets_users.last_name) LIKE ?', ["%$search%", "%$search%"]) | |
->orWhere('assets_users.username', 'LIKE', '%'.$search.'%') | |
->orWhere('assets_locations.name', 'LIKE', '%'.$search.'%') | |
->orWhere('assigned_assets.name', 'LIKE', '%'.$search.'%'); | |
})->orWhere('assets.name', 'LIKE', '%'.$search.'%') | |
->orWhere('assets.asset_tag', 'LIKE', '%'.$search.'%') | |
->orWhere('assets.serial', 'LIKE', '%'.$search.'%') | |
->orWhere('assets.order_number', 'LIKE', '%'.$search.'%') | |
->orWhere('assets.notes', 'LIKE', '%'.$search.'%'); | |
} | |
})->withTrashed()->whereNull("assets.deleted_at"); //workaround for laravel bug | |
} | |
/** | |
* Query builder scope to search on text filters for complex Bootstrap Tables API | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* @param text $filter JSON array of search keys and terms | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeByFilter($query, $filter) | |
{ | |
return $query->where(function ($query) use ($filter) { | |
foreach ($filter as $key => $search_val) { | |
$fieldname = str_replace('custom_fields.','', $key) ; | |
if ($fieldname =='asset_tag') { | |
$query->where('assets.asset_tag', 'LIKE', '%'.$search_val.'%'); | |
} | |
if ($fieldname =='name') { | |
$query->where('assets.name', 'LIKE', '%'.$search_val.'%'); | |
} | |
if ($fieldname =='product_key') { | |
$query->where('assets.serial', 'LIKE', '%'.$search_val.'%'); | |
} | |
if ($fieldname =='purchase_date') { | |
$query->where('assets.purchase_date', 'LIKE', '%'.$search_val.'%'); | |
} | |
if ($fieldname =='purchase_cost') { | |
$query->where('assets.purchase_cost', 'LIKE', '%'.$search_val.'%'); | |
} | |
if ($fieldname =='notes') { | |
$query->where('assets.notes', 'LIKE', '%'.$search_val.'%'); | |
} | |
if ($fieldname =='order_number') { | |
$query->where('assets.order_number', 'LIKE', '%'.$search_val.'%'); | |
} | |
if ($fieldname =='status_label') { | |
$query->whereHas('assetstatus', function ($query) use ($search_val) { | |
$query->where('status_labels.name', 'LIKE', '%' . $search_val . '%'); | |
}); | |
} | |
if ($fieldname =='location') { | |
$query->whereHas('location', function ($query) use ($search_val) { | |
$query->where('locations.name', 'LIKE', '%' . $search_val . '%'); | |
}); | |
} | |
if ($fieldname =='checkedout_to') { | |
$query->whereHas('assigneduser', function ($query) use ($search_val) { | |
$query->where(function ($query) use ($search_val) { | |
$query->where('users.first_name', 'LIKE', '%' . $search_val . '%') | |
->orWhere('users.last_name', 'LIKE', '%' . $search_val . '%'); | |
}); | |
}); | |
} | |
if ($fieldname =='manufacturer') { | |
$query->whereHas('model', function ($query) use ($search_val) { | |
$query->whereHas('manufacturer', function ($query) use ($search_val) { | |
$query->where(function ($query) use ($search_val) { | |
$query->where('manufacturers.name', 'LIKE', '%'.$search_val.'%'); | |
}); | |
}); | |
}); | |
} | |
if ($fieldname =='category') { | |
$query->whereHas('model', function ($query) use ($search_val) { | |
$query->whereHas('category', function ($query) use ($search_val) { | |
$query->where(function ($query) use ($search_val) { | |
$query->where('categories.name', 'LIKE', '%' . $search_val . '%') | |
->orWhere('models.name', 'LIKE', '%' . $search_val . '%') | |
->orWhere('models.model_number', 'LIKE', '%' . $search_val . '%'); | |
}); | |
}); | |
}); | |
} | |
if ($fieldname =='model') { | |
$query->where(function ($query) use ($search_val) { | |
$query->whereHas('model', function ($query) use ($search_val) { | |
$query->where('models.name', 'LIKE', '%' . $search_val . '%'); | |
}); | |
}); | |
} | |
if ($fieldname =='model_number') { | |
$query->where(function ($query) use ($search_val) { | |
$query->whereHas('model', function ($query) use ($search_val) { | |
$query->where('models.model_number', 'LIKE', '%' . $search_val . '%'); | |
}); | |
}); | |
} | |
if ($fieldname =='company') { | |
$query->where(function ($query) use ($search_val) { | |
$query->whereHas('company', function ($query) use ($search_val) { | |
$query->where('companies.name', 'LIKE', '%' . $search_val . '%'); | |
}); | |
}); | |
} | |
if ($fieldname =='supplier') { | |
$query->where(function ($query) use ($search_val) { | |
$query->whereHas('supplier', function ($query) use ($search_val) { | |
$query->where('suppliers.name', 'LIKE', '%' . $search_val . '%'); | |
}); | |
}); | |
} | |
/** | |
* THIS CLUNKY BIT IS VERY IMPORTANT | |
* | |
* Although inelegant, this section matters a lot when querying against fields that do not | |
* exist on the asset table. There's probably a better way to do this moving forward, for | |
* example using the Schema:: methods to determine whether or not a column actually exists, | |
* or even just using the $searchableRelations variable earlier in this file. | |
* | |
* In short, this set of statements tells the query builder to ONLY query against an | |
* actual field that's being passed if it doesn't meet known relational fields. This | |
* allows us to query custom fields directly in the assetsv table | |
* (regardless of their name) and *skip* any fields that we already know can only be | |
* searched through relational searches that we do earlier in this method. | |
* | |
* For example, we do not store "location" as a field on the assets table, we store | |
* that relationship through location_id on the assets table, therefore querying | |
* assets.location would fail, as that field doesn't exist -- plus we're already searching | |
* against those relationships earlier in this method. | |
* | |
* - snipe | |
* | |
*/ | |
if ( | |
($fieldname!='category') && | |
($fieldname!='model_number') && | |
($fieldname!='rtd_location') && | |
($fieldname!='location') && | |
($fieldname!='supplier') && | |
($fieldname!='status_label') && | |
($fieldname!='model') && | |
($fieldname!='company') && | |
($fieldname!='manufacturer') | |
) { | |
$query->where('assets.'.$fieldname, 'LIKE', '%' . $search_val . '%'); | |
} | |
} | |
}); | |
} | |
/** | |
* Query builder scope to order on model | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* @param text $order Order | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeOrderModels($query, $order) | |
{ | |
return $query->join('models as asset_models', 'assets.model_id', '=', 'asset_models.id')->orderBy('asset_models.name', $order); | |
} | |
/** | |
* Query builder scope to order on model number | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* @param text $order Order | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeOrderModelNumber($query, $order) | |
{ | |
return $query->join('models', 'assets.model_id', '=', 'models.id')->orderBy('models.model_number', $order); | |
} | |
/** | |
* Query builder scope to order on assigned user | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* @param text $order Order | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeOrderAssigned($query, $order) | |
{ | |
return $query->leftJoin('users as users_sort', 'assets.assigned_to', '=', 'users_sort.id')->select('assets.*')->orderBy('users_sort.first_name', $order)->orderBy('users_sort.last_name', $order); | |
} | |
/** | |
* Query builder scope to order on status | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* @param text $order Order | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeOrderStatus($query, $order) | |
{ | |
return $query->join('status_labels as status_sort', 'assets.status_id', '=', 'status_sort.id')->orderBy('status_sort.name', $order); | |
} | |
/** | |
* Query builder scope to order on company | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* @param text $order Order | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeOrderCompany($query, $order) | |
{ | |
return $query->leftJoin('companies as company_sort', 'assets.company_id', '=', 'company_sort.id')->orderBy('company_sort.name', $order); | |
} | |
/** | |
* Query builder scope to return results of a category | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* @param text $order Order | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeInCategory($query, $category_id) | |
{ | |
return $query->join('models as category_models', 'assets.model_id', '=', 'category_models.id') | |
->join('categories', 'category_models.category_id', '=', 'categories.id')->where('category_models.category_id', '=', $category_id); | |
} | |
/** | |
* Query builder scope to return results of a manufacturer | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* @param text $order Order | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeByManufacturer($query, $manufacturer_id) | |
{ | |
return $query->join('models', 'assets.model_id', '=', 'models.id') | |
->join('manufacturers', 'models.manufacturer_id', '=', 'manufacturers.id')->where('models.manufacturer_id', '=', $manufacturer_id); | |
} | |
/** | |
* Query builder scope to order on category | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* @param text $order Order | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeOrderCategory($query, $order) | |
{ | |
return $query->join('models as order_model_category', 'assets.model_id', '=', 'order_model_category.id') | |
->join('categories as category_order', 'order_model_category.category_id', '=', 'category_order.id') | |
->orderBy('category_order.name', $order); | |
} | |
/** | |
* Query builder scope to order on manufacturer | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* @param text $order Order | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeOrderManufacturer($query, $order) | |
{ | |
return $query->join('models', 'assets.model_id', '=', 'models.id') | |
->join('manufacturers', 'models.manufacturer_id', '=', 'manufacturers.id') | |
->orderBy('manufacturers.name', $order); | |
} | |
/** | |
* Query builder scope to order on location | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* @param text $order Order | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeOrderLocation($query, $order) | |
{ | |
return $query->leftJoin('locations as asset_locations', 'asset_locations.id', '=', 'assets.location_id')->orderBy('asset_locations.name', $order); | |
} | |
/** | |
* Query builder scope to order on default | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* @param text $order Order | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeOrderRtdLocation($query, $order) | |
{ | |
return $query->leftJoin('locations as rtd_asset_locations', 'rtd_asset_locations.id', '=', 'assets.rtd_location_id')->orderBy('rtd_asset_locations.name', $order); | |
} | |
/** | |
* Query builder scope to order on supplier name | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* @param text $order Order | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeOrderSupplier($query, $order) | |
{ | |
return $query->leftJoin('suppliers as suppliers_assets', 'assets.supplier_id', '=', 'suppliers_assets.id')->orderBy('suppliers_assets.name', $order); | |
} | |
/** | |
* Query builder scope to search on location ID | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* @param text $search Search term | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeByLocationId($query, $search) | |
{ | |
return $query->where(function ($query) use ($search) { | |
$query->whereHas('location', function ($query) use ($search) { | |
$query->where('locations.id', '=', $search); | |
}); | |
}); | |
} | |
/** | |
* Query builder scope to search on location ID | |
* | |
* @param \Illuminate\Database\Query\Builder $query Query builder instance | |
* @param text $search Search term | |
* | |
* @return \Illuminate\Database\Query\Builder Modified query builder | |
*/ | |
public function scopeByDepreciationId($query, $search) | |
{ | |
return $query->join('models', 'assets.model_id', '=', 'models.id') | |
->join('depreciations', 'models.depreciation_id', '=', 'depreciations.id')->where('models.depreciation_id', '=', $search); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/bootstrap-table.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/extensions/mobile/bootstrap-table-mobile.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/extensions/export/bootstrap-table-export.min.js"></script> | |
{{-- <script src="{{ asset('js/extensions/export/jquery.base64.js') }}"></script> --}} | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/bower_components/file-saver/FileSaver.min.js"></script> | |
{{-- <script src="{{ asset('js/xlsx.core.min.js') }}"></script> --}} | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/bower_components/jspdf/dist/jspdf.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/bower_components/jspdf-autotable/dist/jspdf.plugin.autotable.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/tableExport.min.js"></script> | |
@if (!isset($simple_view)) | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/extensions/toolbar/bootstrap-table-toolbar.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/extensions/sticky-header/bootstrap-table-sticky-header.min.js"></script> | |
@endif | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/extensions/cookie/bootstrap-table-cookie.min.js"></script> | |
<script nonce="{{ csrf_token() }}"> | |
$(function () { | |
var stickyHeaderOffsetY = 0; | |
if ( $('.navbar-fixed-top').css('height') ) { | |
stickyHeaderOffsetY = +$('.navbar-fixed-top').css('height').replace('px',''); | |
} | |
if ( $('.navbar-fixed-top').css('margin-bottom') ) { | |
stickyHeaderOffsetY += +$('.navbar-fixed-top').css('margin-bottom').replace('px',''); | |
} | |
$('.snipe-table').bootstrapTable('destroy').bootstrapTable({ | |
classes: 'table table-responsive table-no-bordered', | |
ajaxOptions: { | |
headers: { | |
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') | |
} | |
}, | |
stickyHeader: true, | |
stickyHeaderOffsetY: stickyHeaderOffsetY + 'px', | |
undefinedText: '', | |
iconsPrefix: 'fa', | |
cookie: true, | |
cookieExpire: '2y', | |
cookieIdTable: '{{ Route::currentRouteName() }}', | |
mobileResponsive: true, | |
maintainSelected: true, | |
trimOnSearch: false, | |
paginationFirstText: "{{ trans('general.first') }}", | |
paginationLastText: "{{ trans('general.last') }}", | |
paginationPreText: "{{ trans('general.previous') }}", | |
paginationNextText: "{{ trans('general.next') }}", | |
pageList: ['10','20', '30','50','100','150','200', '500'], | |
pageSize: {{ (($snipeSettings->per_page!='') && ($snipeSettings->per_page > 0)) ? $snipeSettings->per_page : 20 }}, | |
paginationVAlign: 'both', | |
formatLoadingMessage: function () { | |
return '<h4><i class="fa fa-spinner fa-spin" aria-hidden="true"></i> Loading... please wait.... </h4>'; | |
}, | |
icons: { | |
advancedSearchIcon: 'fa fa-search-plus', | |
paginationSwitchDown: 'fa-caret-square-o-down', | |
paginationSwitchUp: 'fa-caret-square-o-up', | |
columns: 'fa-columns', | |
refresh: 'fa-refresh', | |
export: 'fa-download' | |
}, | |
exportTypes: ['csv', 'excel', 'doc', 'txt','json', 'xml', 'pdf'], | |
}); | |
}); | |
function dateRowCheckStyle(value) { | |
if ((value.days_to_next_audit) && (value.days_to_next_audit < {{ $snipeSettings->audit_warning_days ?: 0 }})) { | |
return { classes : "danger" } | |
} | |
return {}; | |
} | |
// Handle whether or not the edit button should be disabled | |
$('.snipe-table').on('check.bs.table', function () { | |
$('#bulkEdit').removeAttr('disabled'); | |
}); | |
$('.snipe-table').on('check-all.bs.table', function () { | |
$('#bulkEdit').removeAttr('disabled'); | |
}); | |
$('.snipe-table').on('uncheck.bs.table', function () { | |
if ($('.snipe-table').bootstrapTable('getSelections').length == 0) { | |
$('#bulkEdit').attr('disabled', 'disabled'); | |
} | |
}); | |
$('.snipe-table').on('uncheck-all.bs.table', function (e, row) { | |
$('#bulkEdit').attr('disabled', 'disabled'); | |
}); | |
// This only works for model index pages because it uses the row's model ID | |
function genericRowLinkFormatter(destination) { | |
return function (value,row) { | |
if (value) { | |
return '<a href="{{ url('/') }}/' + destination + '/' + row.id + '"> ' + value + '</a>'; | |
} | |
}; | |
} | |
// Use this when we're introspecting into a column object and need to link | |
function genericColumnObjLinkFormatter(destination) { | |
return function (value,row) { | |
if ((value) && (value.status_meta)) { | |
var text_color; | |
var icon_style; | |
var text_help; | |
var status_meta = { | |
'deployed': '{{ strtolower(trans('general.deployed')) }}', | |
'deployable': '{{ strtolower(trans('admin/hardware/general.deployable')) }}', | |
'pending': '{{ strtolower(trans('general.pending')) }}' | |
} | |
switch (value.status_meta) { | |
case 'deployed': | |
text_color = 'blue'; | |
icon_style = 'fa-circle'; | |
text_help = '<label class="label label-default">{{ trans('general.deployed') }}</label>'; | |
break; | |
case 'deployable': | |
text_color = 'green'; | |
icon_style = 'fa-circle'; | |
text_help = ''; | |
break; | |
case 'pending': | |
text_color = 'orange'; | |
icon_style = 'fa-circle'; | |
text_help = ''; | |
break; | |
default: | |
text_color = 'red'; | |
icon_style = 'fa-times'; | |
text_help = ''; | |
} | |
return '<nobr><a href="{{ url('/') }}/' + destination + '/' + value.id + '" data-tooltip="true" title="'+ status_meta[value.status_meta] + '"> <i class="fa ' + icon_style + ' text-' + text_color + '"></i> ' + value.name + ' ' + text_help + ' </a> </nobr>'; | |
} else if ((value) && (value.name)) { | |
// Add some overrides for any funny urls we have | |
var dest = destination; | |
if (destination=='fieldsets') { | |
var dest = 'fields/fieldsets'; | |
} | |
return '<nobr><a href="{{ url('/') }}/' + dest + '/' + value.id + '"> ' + value.name + '</a></span>'; | |
} | |
}; | |
} | |
function hardwareAuditFormatter(value, row) { | |
return '<a href="{{ url('/') }}/hardware/audit/' + row.id + '/" class="btn btn-sm bg-yellow" data-tooltip="true" title="Audit this item">{{ trans('general.audit') }}</a>'; | |
} | |
// Make the edit/delete buttons | |
function genericActionsFormatter(destination) { | |
return function (value,row) { | |
var actions = '<nobr>'; | |
// Add some overrides for any funny urls we have | |
var dest = destination; | |
if (destination=='groups') { | |
var dest = 'admin/groups'; | |
} | |
if (destination=='maintenances') { | |
var dest = 'hardware/maintenances'; | |
} | |
if ((row.available_actions) && (row.available_actions.clone === true)) { | |
actions += '<a href="{{ url('/') }}/' + dest + '/' + row.id + '/clone" class="btn btn-sm btn-info" data-tooltip="true" title="Clone"><i class="fa fa-copy"></i></a> '; | |
} | |
if ((row.available_actions) && (row.available_actions.update === true)) { | |
actions += '<a href="{{ url('/') }}/' + dest + '/' + row.id + '/edit" class="btn btn-sm btn-warning" data-tooltip="true" title="Update"><i class="fa fa-pencil"></i></a> '; | |
} | |
if ((row.available_actions) && (row.available_actions.delete === true)) { | |
actions += '<a href="{{ url('/') }}/' + dest + '/' + 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> '; | |
} else { | |
actions += '<a class="btn btn-danger btn-sm delete-asset disabled" onClick="return false;"><i class="fa fa-trash"></i></a> '; | |
} | |
if ((row.available_actions) && (row.available_actions.restore === true)) { | |
actions += '<a href="{{ url('/') }}/' + dest + '/' + row.id + '/restore" class="btn btn-sm btn-warning" data-tooltip="true" title="Restore"><i class="fa fa-retweet"></i></a> '; | |
} | |
actions +='</nobr>'; | |
return actions; | |
}; | |
} | |
// This handles the icons and display of polymorphic entries | |
function polymorphicItemFormatter(value) { | |
var item_destination = ''; | |
var item_icon; | |
if ((value) && (value.type)) { | |
if (value.type == 'asset') { | |
item_destination = 'hardware'; | |
item_icon = 'fa-barcode'; | |
} else if (value.type == 'accessory') { | |
item_destination = 'accessories'; | |
item_icon = 'fa-keyboard-o'; | |
} else if (value.type == 'component') { | |
item_destination = 'components'; | |
item_icon = 'fa-hdd-o'; | |
} else if (value.type == 'consumable') { | |
item_destination = 'consumables'; | |
item_icon = 'fa-tint'; | |
} else if (value.type == 'license') { | |
item_destination = 'licenses'; | |
item_icon = 'fa-floppy-o'; | |
} else if (value.type == 'user') { | |
item_destination = 'users'; | |
item_icon = 'fa-user'; | |
} else if (value.type == 'location') { | |
item_destination = 'locations' | |
item_icon = 'fa-map-marker'; | |
} | |
return '<nobr><a href="{{ url('/') }}/' + item_destination +'/' + value.id + '" data-tooltip="true" title="' + value.type + '"><i class="fa ' + item_icon + ' text-blue"></i> ' + value.name + '</a></nobr>'; | |
} else { | |
return ''; | |
} | |
} | |
// This just prints out the item type in the activity report | |
function itemTypeFormatter(value, row) { | |
if ((row) && (row.item) && (row.item.type)) { | |
return row.item.type; | |
} | |
} | |
// Convert line breaks to <br> | |
function notesFormatter(value) { | |
if (value) { | |
return value.replace(/(?:\r\n|\r|\n)/g, '<br />');; | |
} | |
} | |
// We need a special formatter for license seats, since they don't work exactly the same | |
// Checkouts need the license ID, checkins need the specific seat ID | |
function licenseSeatInOutFormatter(value, row) { | |
// The user is allowed to check the license seat out and it's available | |
if ((row.available_actions.checkout == true) && (row.user_can_checkout == true) && ((!row.asset_id) && (!row.assigned_to))) { | |
return '<a href="{{ url('/') }}/licenses/' + row.license_id + '/checkout/'+row.id+'" class="btn btn-sm bg-maroon" data-tooltip="true" title="Check this item out">{{ trans('general.checkout') }}</a>'; | |
} else { | |
return '<a href="{{ url('/') }}/licenses/' + row.id + '/checkin" class="btn btn-sm bg-purple" data-tooltip="true" title="Check in this license seat.">{{ trans('general.checkin') }}</a>'; | |
} | |
} | |
function genericCheckinCheckoutFormatter(destination) { | |
return function (value,row) { | |
// The user is allowed to check items out, AND the item is deployable | |
if ((row.available_actions.checkout == true) && (row.user_can_checkout == true) && ((!row.asset_id) && (!row.assigned_to))) { | |
return '<a href="{{ url('/') }}/' + destination + '/' + row.id + '/checkout" class="btn btn-sm bg-maroon" data-tooltip="true" title="Check this item out">{{ trans('general.checkout') }}</a>'; | |
// The user is allowed to check items out, but the item is not deployable | |
} else if (((row.user_can_checkout == false)) && (row.available_actions.checkout == true) && (!row.assigned_to)) { | |
return '<div data-tooltip="true" title="This item has a status label that is undeployable and cannot be checked out at this time."><a class="btn btn-sm bg-maroon disabled">{{ trans('general.checkout') }}</a></div>'; | |
// The user is allowed to check items in | |
} else if (row.available_actions.checkin == true) { | |
if (row.assigned_to) { | |
return '<a href="{{ url('/') }}/' + destination + '/' + row.id + '/checkin" class="btn btn-sm bg-purple" data-tooltip="true" title="Check this item in so it is available for re-imaging, re-issue, etc.">{{ trans('general.checkin') }}</a>'; | |
} else if (row.assigned_pivot_id) { | |
return '<a href="{{ url('/') }}/' + destination + '/' + row.assigned_pivot_id + '/checkin" class="btn btn-sm bg-purple" data-tooltip="true" title="Check this item in so it is available for re-imaging, re-issue, etc.">{{ trans('general.checkin') }}</a>'; | |
} | |
} | |
} | |
} | |
// This is only used by the requestable assets section | |
function assetRequestActionsFormatter (row, value) { | |
if (value.available_actions.cancel == true) { | |
return '<form action="{{ url('/') }}/account/request-asset/'+ value.id + '" method="GET"><button class="btn btn-danger btn-sm" data-tooltip="true" title="Cancel this item request">{{ trans('button.cancel') }}</button></form>'; | |
} else if (value.available_actions.request == true) { | |
return '<form action="{{ url('/') }}/account/request-asset/'+ value.id + '" method="GET"><button class="btn btn-primary btn-sm" data-tooltip="true" title="Request this item">{{ trans('button.request') }}</button></form>'; | |
} | |
} | |
var formatters = [ | |
'hardware', | |
'accessories', | |
'consumables', | |
'components', | |
'locations', | |
'users', | |
'manufacturers', | |
'maintenances', | |
'statuslabels', | |
'models', | |
'licenses', | |
'categories', | |
'suppliers', | |
'departments', | |
'companies', | |
'depreciations', | |
'fieldsets', | |
'groups' | |
]; | |
for (var i in formatters) { | |
window[formatters[i] + 'LinkFormatter'] = genericRowLinkFormatter(formatters[i]); | |
window[formatters[i] + 'LinkObjFormatter'] = genericColumnObjLinkFormatter(formatters[i]); | |
window[formatters[i] + 'ActionsFormatter'] = genericActionsFormatter(formatters[i]); | |
window[formatters[i] + 'InOutFormatter'] = genericCheckinCheckoutFormatter(formatters[i]); | |
} | |
// This is gross, but necessary so that we can package the API response | |
// for custom fields in a more useful way. | |
function customFieldsFormatter(value, row) { | |
if ((!this) || (!this.title)) { | |
return ''; | |
} | |
var field_column = this.title; | |
// Pull out any HTMl that might be passed via the presenter | |
// (for example, the locked icon for encrypted fields) | |
var field_column_plain = field_column.replace(/<(?:.|\n)*?> ?/gm, ''); | |
if ((row.custom_fields) && (row.custom_fields[field_column_plain])) { | |
// If the field type needs special formatting, do that here | |
if ((row.custom_fields[field_column_plain].field_format) && (row.custom_fields[field_column_plain].value)) { | |
if (row.custom_fields[field_column_plain].field_format=='URL') { | |
return '<a href="' + row.custom_fields[field_column_plain].value + '" target="_blank" rel="noopener">' + row.custom_fields[field_column_plain].value + '</a>'; | |
} else if (row.custom_fields[field_column_plain].field_format=='EMAIL') { | |
return '<a href="mailto:' + row.custom_fields[field_column_plain].value + '">' + row.custom_fields[field_column_plain].value + '</a>'; | |
} | |
} | |
return row.custom_fields[field_column_plain].value; | |
} | |
} | |
function createdAtFormatter(value) { | |
if ((value) && (value.date)) { | |
return value.date; | |
} | |
} | |
function groupsFormatter(value) { | |
if (value) { | |
var groups = ''; | |
for (var index in value.rows) { | |
groups += '<a href="{{ url('/') }}/admin/groups/' + value.rows[index].id + '" class="label label-default"> ' + value.rows[index].name + '</a> '; | |
} | |
return groups; | |
} | |
} | |
function changeLogFormatter(value) { | |
var result = ''; | |
for (var index in value) { | |
result += index + ': <del>' + value[index].old + '</del> <i class="fa fa-long-arrow-right" aria-hidden="true"></i> ' + value[index].new + '<br>' | |
} | |
return result; | |
} | |
// Create a linked phone number in the table list | |
function phoneFormatter(value) { | |
if (value) { | |
return '<a href="tel:' + value + '">' + value + '</a>'; | |
} | |
} | |
function deployedLocationFormatter(row, value) { | |
if ((row) && (row!=undefined)) { | |
return '<a href="{{ url('/') }}/locations/' + row.id + '"> ' + row.name + '</a>'; | |
} else if (value.rtd_location) { | |
return '<a href="{{ url('/') }}/locations/' + value.rtd_location.id + '" data-tooltip="true" title="Default Location"> ' + value.rtd_location.name + '</a>'; | |
} | |
} | |
function groupsAdminLinkFormatter(value, row) { | |
return '<a href="{{ url('/') }}/admin/groups/' + row.id + '"> ' + value + '</a>'; | |
} | |
function assetTagLinkFormatter(value, row) { | |
if ((row.asset) && (row.asset.id)) { | |
return '<a href="{{ url('/') }}/hardware/' + row.asset.id + '"> ' + row.asset.asset_tag + '</a>'; | |
} | |
return ''; | |
} | |
function assetNameLinkFormatter(value, row) { | |
if ((row.asset) && (row.asset.name)) { | |
return '<a href="{{ url('/') }}/hardware/' + row.asset.id + '"> ' + row.asset.name + '</a>'; | |
} | |
} | |
function trueFalseFormatter(value) { | |
if ((value) && ((value == 'true') || (value == '1'))) { | |
return '<i class="fa fa-check text-success"></i>'; | |
} else { | |
return '<i class="fa fa-times text-danger"></i>'; | |
} | |
} | |
function dateDisplayFormatter(value) { | |
if (value) { | |
return value.formatted; | |
} | |
} | |
function iconFormatter(value) { | |
if (value) { | |
return '<i class="' + value + ' icon-med"></i>'; | |
} | |
} | |
function emailFormatter(value) { | |
if (value) { | |
return '<a href="mailto:' + value + '"> ' + value + '</a>'; | |
} | |
} | |
function linkFormatter(value) { | |
if (value) { | |
return '<a href="' + value + '"> ' + value + '</a>'; | |
} | |
} | |
function assetCompanyFilterFormatter(value, row) { | |
if (value) { | |
return '<a href="{{ url('/') }}/hardware/?company_id=' + row.id + '"> ' + value + '</a>'; | |
} | |
} | |
function assetCompanyObjFilterFormatter(value, row) { | |
if ((row) && (row.company)) { | |
return '<a href="{{ url('/') }}/hardware/?company_id=' + row.company.id + '"> ' + row.company.name + '</a>'; | |
} | |
} | |
function usersCompanyObjFilterFormatter(value, row) { | |
if (value) { | |
return '<a href="{{ url('/') }}/users/?company_id=' + row.id + '"> ' + value + '</a>'; | |
} else { | |
return value; | |
} | |
} | |
function employeeNumFormatter(value, row) { | |
if ((row) && (row.assigned_to) && ((row.assigned_to.employee_number))) { | |
return '<a href="{{ url('/') }}/users/' + row.assigned_to.id + '"> ' + row.assigned_to.employee_number + '</a>'; | |
} | |
} | |
function orderNumberObjFilterFormatter(value, row) { | |
if (value) { | |
return '<a href="{{ url('/') }}/hardware/?order_number=' + row.order_number + '"> ' + row.order_number + '</a>'; | |
} | |
} | |
function imageFormatter(value) { | |
if (value) { | |
return '<a href="' + value + '" data-toggle="lightbox" data-type="image"><img src="' + value + '" style="max-height: {{ $snipeSettings->thumbnail_max_h }}px; width: auto;" class="img-responsive"></a>'; | |
} | |
} | |
function fileUploadFormatter(value) { | |
if ((value) && (value.url) && (value.inlineable)) { | |
return '<a href="' + value.url + '" data-toggle="lightbox" data-type="image"><img src="' + value.url + '" style="max-height: {{ $snipeSettings->thumbnail_max_h }}px; width: auto;" class="img-responsive"></a>'; | |
} else if ((value) && (value.url)) { | |
return '<a href="' + value.url + '" class="btn btn-default"><i class="fa fa-download"></i></a>'; | |
} | |
} | |
function fileUploadNameFormatter(value) { | |
console.dir(value); | |
if ((value) && (value.filename) && (value.url)) { | |
return '<a href="' + value.url + '">' + value.filename + '</a>'; | |
} | |
} | |
function sumFormatter(data) { | |
if (Array.isArray(data)) { | |
var field = this.field; | |
var total_sum = data.reduce(function(sum, row) { | |
return (sum) + (parseFloat(row[field]) || 0); | |
}, 0); | |
return total_sum.toFixed(2); | |
} | |
return 'not an array'; | |
} | |
$(function () { | |
$('#bulkEdit').click(function () { | |
var selectedIds = $('.snipe-table').bootstrapTable('getSelections'); | |
$.each(selectedIds, function(key,value) { | |
$( "#bulkForm" ).append($('<input type="hidden" name="ids[' + value.id + ']" value="' + value.id + '">' )); | |
}); | |
}); | |
}); | |
// This is necessary to make the bootstrap tooltips work inside of the | |
// wenzhixin/bootstrap-table formatters | |
$(function() { | |
$('#table').on('post-body.bs.table', function () { | |
$('[data-tooltip="true"]').tooltip({ | |
container: 'body' | |
}); | |
}); | |
}); | |
</script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<title> | |
@section('title') | |
@show | |
:: {{ $snipeSettings->site_name }} | |
</title> | |
<!-- Tell the browser to be responsive to screen width --> | |
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> | |
<meta name="apple-mobile-web-app-capable" content="yes"> | |
<link rel="apple-touch-icon" href="{{ url('/') }}/uploads/{{ $snipeSettings->logo }}"> | |
<link rel="apple-touch-startup-image" href="{{ url('/') }}/uploads/{{ $snipeSettings->logo }}"> | |
<!-- Select2 --> | |
<link rel="stylesheet" href="{{ url(asset('js/plugins/select2/select2.min.css')) }}"> | |
<!-- iCheck for checkboxes and radio inputs --> | |
<link rel="stylesheet" href="{{ url(asset('js/plugins/iCheck/all.css')) }}"> | |
<!-- bootstrap tables CSS --> | |
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/bootstrap-table.min.css"> | |
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/extensions/sticky-header/bootstrap-table-sticky-header.min.css"> | |
<link rel="stylesheet" href="{{ url(mix('css/dist/all.css')) }}"> | |
<link rel="shortcut icon" type="image/ico" href="{{ url(asset('favicon.ico')) }}"> | |
<meta name="csrf-token" content="{{ csrf_token() }}"> | |
<meta name="baseUrl" content="{{ url('/') }}/"> | |
<script nonce="{{ csrf_token() }}"> | |
window.Laravel = { csrfToken: '{{ csrf_token() }}' }; | |
</script> | |
@if (($snipeSettings) && ($snipeSettings->skin!='')) | |
<link rel="stylesheet" href="{{ url('css/skins/skin-'.$snipeSettings->skin) }}.css"> | |
@endif | |
<style nonce="{{ csrf_token() }}"> | |
@if (($snipeSettings) && ($snipeSettings->header_color!='')) | |
.main-header .navbar, .main-header .logo { | |
background-color: {{ $snipeSettings->header_color }}; | |
background: -webkit-linear-gradient(top, {{ $snipeSettings->header_color }} 0%,{{ $snipeSettings->header_color }} 100%); | |
background: linear-gradient(to bottom, {{ $snipeSettings->header_color }} 0%,{{ $snipeSettings->header_color }} 100%); | |
border-color: {{ $snipeSettings->header_color }}; | |
} | |
.skin-blue .sidebar-menu > li:hover > a, .skin-blue .sidebar-menu > li.active > a { | |
border-left-color: {{ $snipeSettings->header_color }}; | |
} | |
.btn-primary { | |
background-color: {{ $snipeSettings->header_color }}; | |
border-color: {{ $snipeSettings->header_color }}; | |
} | |
@endif | |
@media (max-width: 400px) { | |
.navbar-left { | |
margin: 2px; | |
} | |
.nav::after { | |
clear: none; | |
} | |
} | |
</style> | |
@if (($snipeSettings) && ($snipeSettings->custom_css)) | |
<style> | |
{!! $snipeSettings->show_custom_css() !!} | |
</style> | |
@endif | |
<script nonce="{{ csrf_token() }}"> | |
window.snipeit = { | |
settings: { | |
"per_page": {{ $snipeSettings->per_page }} | |
} | |
}; | |
</script> | |
<!-- Add laravel routes into javascript Primarily useful for vue.--> | |
@routes | |
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> | |
<!-- WARNING: Respond.js doesn't work if you view the page via file:// --> | |
<!--[if lt IE 9]> | |
@if ($snipeSettings->load_remote=='1') | |
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js" integrity="sha384-qFIkRsVO/J5orlMvxK1sgAt2FXT67og+NyFTITYzvbIP1IJavVEKZM7YWczXkwpB" crossorigin="anonymous"></script> | |
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script> | |
@else | |
<script src="{{ url(asset('js/html5shiv.js')) }}" nonce="{{ csrf_token() }}"></script> | |
<script src="{{ url(asset('js/respond.js')) }}" nonce="{{ csrf_token() }}"></script> | |
@endif | |
<![endif]--> | |
</head> | |
<body class="sidebar-mini skin-blue {{ (session('menu_state')!='open') ? 'sidebar-mini sidebar-collapse' : '' }}"> | |
<div class="wrapper"> | |
<header class="main-header"> | |
<!-- Logo --> | |
<!-- Header Navbar: style can be found in header.less --> | |
<nav class="navbar navbar-static-top" role="navigation"> | |
<!-- Sidebar toggle button above the compact sidenav --> | |
<a href="#" style="color: white" class="sidebar-toggle btn btn-white" data-toggle="offcanvas" role="button"> | |
<span class="sr-only">Toggle navigation</span> | |
</a> | |
<ul class="nav navbar-nav navbar-left"> | |
<li class="left-navblock"> | |
@if ($snipeSettings->brand == '3') | |
<a class="logo navbar-brand no-hover" href="{{ url('/') }}"> | |
@if ($snipeSettings->logo!='') | |
<img class="navbar-brand-img" src="{{ url('/') }}/uploads/{{ $snipeSettings->logo }}"> | |
@endif | |
{{ $snipeSettings->site_name }} | |
</a> | |
@elseif ($snipeSettings->brand == '2') | |
<a class="logo navbar-brand no-hover" href="{{ url('/') }}"> | |
@if ($snipeSettings->logo!='') | |
<img class="navbar-brand-img" src="{{ url('/') }}/uploads/{{ $snipeSettings->logo }}"> | |
@endif | |
</a> | |
@else | |
<a class="logo no-hover" href="{{ url('/') }}"> | |
{{ $snipeSettings->site_name }} | |
</a> | |
@endif | |
</li> | |
</ul> | |
<!-- Navbar Right Menu --> | |
<div class="navbar-custom-menu"> | |
<ul class="nav navbar-nav"> | |
@can('index', \App\Models\Asset::class) | |
<li {!! (Request::is('hardware*') ? ' class="active"' : '') !!}> | |
<a href="{{ url('hardware') }}"> | |
<i class="fa fa-barcode"></i> | |
</a> | |
</li> | |
@endcan | |
@can('view', \App\Models\License::class) | |
<li {!! (Request::is('licenses*') ? ' class="active"' : '') !!}> | |
<a href="{{ route('licenses.index') }}"> | |
<i class="fa fa-floppy-o"></i> | |
</a> | |
</li> | |
@endcan | |
@can('index', \App\Models\Accessory::class) | |
<li {!! (Request::is('accessories*') ? ' class="active"' : '') !!}> | |
<a href="{{ route('accessories.index') }}"> | |
<i class="fa fa-keyboard-o"></i> | |
</a> | |
</li> | |
@endcan | |
@can('index', \App\Models\Consumable::class) | |
<li {!! (Request::is('consumables*') ? ' class="active"' : '') !!}> | |
<a href="{{ url('consumables') }}"> | |
<i class="fa fa-tint"></i> | |
</a> | |
</li> | |
@endcan | |
@can('view', \App\Models\Component::class) | |
<li {!! (Request::is('components*') ? ' class="active"' : '') !!}> | |
<a href="{{ route('components.index') }}"> | |
<i class="fa fa-hdd-o"></i> | |
</a> | |
</li> | |
@endcan | |
@can('index', \App\Models\Asset::class) | |
<form class="navbar-form navbar-left form-horizontal" role="search" action="{{ route('findbytag/hardware') }}" method="get"> | |
<div class="col-xs-12 col-md-12"> | |
<div class="col-xs-12 form-group"> | |
<label class="sr-only" for="tagSearch">{{ trans('general.lookup_by_tag') }}</label> | |
<input type="text" class="form-control" id="tagSearch" name="assetTag" placeholder="{{ trans('general.lookup_by_tag') }}"> | |
<input type="hidden" name="topsearch" value="true"> | |
</div> | |
<div class="col-xs-1"> | |
<button type="submit" class="btn btn-primary pull-right"><i class="fa fa-search"></i></button> | |
</div> | |
</div> | |
</form> | |
@endcan | |
@can('admin') | |
<li class="dropdown"> | |
<a href="#" class="dropdown-toggle" data-toggle="dropdown"> | |
{{ trans('general.create') }} | |
<b class="caret"></b> | |
</a> | |
<ul class="dropdown-menu"> | |
@can('create', \App\Models\Asset::class) | |
<li {!! (Request::is('hardware/create') ? 'class="active>"' : '') !!}> | |
<a href="{{ route('hardware.create') }}"> | |
<i class="fa fa-barcode fa-fw"></i> | |
{{ trans('general.asset') }} | |
</a> | |
</li> | |
@endcan | |
@can('create', \App\Models\License::class) | |
<li {!! (Request::is('licenses/create') ? 'class="active"' : '') !!}> | |
<a href="{{ route('licenses.create') }}"> | |
<i class="fa fa-floppy-o fa-fw"></i> | |
{{ trans('general.license') }} | |
</a> | |
</li> | |
@endcan | |
@can('create', \App\Models\Accessory::class) | |
<li {!! (Request::is('accessories/create') ? 'class="active"' : '') !!}> | |
<a href="{{ route('accessories.create') }}"> | |
<i class="fa fa-keyboard-o fa-fw"></i> | |
{{ trans('general.accessory') }}</a> | |
</li> | |
@endcan | |
@can('create', \App\Models\Consumable::class) | |
<li {!! (Request::is('consunmables/create') ? 'class="active"' : '') !!}> | |
<a href="{{ route('consumables.create') }}"> | |
<i class="fa fa-tint fa-fw"></i> | |
{{ trans('general.consumable') }} | |
</a> | |
</li> | |
@endcan | |
@can('create', \App\Models\Component::class) | |
<li {!! (Request::is('components/create') ? 'class="active"' : '') !!}> | |
<a href="{{ route('components.create') }}"> | |
<i class="fa fa-hdd-o fa-fw"></i> | |
{{ trans('general.component') }} | |
</a> | |
</li> | |
@endcan | |
@can('create', \App\Models\User::class) | |
<li {!! (Request::is('users/create') ? 'class="active"' : '') !!}> | |
<a href="{{ route('users.create') }}"> | |
<i class="fa fa-user fa-fw"></i> | |
{{ trans('general.user') }} | |
</a> | |
</li> | |
@endcan | |
</ul> | |
</li> | |
@endcan | |
@can('admin') | |
@if ($snipeSettings->show_alerts_in_menu=='1') | |
<!-- Tasks: style can be found in dropdown.less --> | |
<?php $alert_items = \App\Helpers\Helper::checkLowInventory(); ?> | |
<li class="dropdown tasks-menu"> | |
<a href="#" class="dropdown-toggle" data-toggle="dropdown"> | |
<i class="fa fa-flag-o"></i> | |
@if (count($alert_items)) | |
<span class="label label-danger">{{ count($alert_items) }}</span> | |
@endif | |
</a> | |
<ul class="dropdown-menu"> | |
<li class="header">You have {{ count($alert_items) }} items below or almost below minimum quantity levels</li> | |
<li> | |
<!-- inner menu: contains the actual data --> | |
<ul class="menu"> | |
@for($i=0; count($alert_items) > $i; $i++) | |
<li><!-- Task item --> | |
<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 | |
</small> | |
</h3> | |
<div class="progress xs"> | |
<div class="progress-bar progress-bar-yellow" style="width: {{ $alert_items[$i]['percent'] }}%" role="progressbar" aria-valuenow="{{ $alert_items[$i]['percent'] }}" aria-valuemin="0" aria-valuemax="100"> | |
<span class="sr-only">{{ $alert_items[$i]['percent'] }}% Complete</span> | |
</div> | |
</div> | |
</a> | |
</li> | |
<!-- end task item --> | |
@endfor | |
</ul> | |
</li> | |
{{-- <li class="footer"> | |
<a href="#">View all tasks</a> | |
</li> --}} | |
</ul> | |
</li> | |
@endcan | |
@endif | |
<!-- User Account: style can be found in dropdown.less --> | |
@if (Auth::check()) | |
<li class="dropdown user user-menu"> | |
<a href="#" class="dropdown-toggle" data-toggle="dropdown"> | |
@if (Auth::user()->present()->gravatar()) | |
<img src="{{ Auth::user()->present()->gravatar() }}" class="user-image" alt="User Image"> | |
@else | |
<i class="fa fa-user fa-fws"></i> | |
@endif | |
<span class="hidden-xs">{{ Auth::user()->first_name }} <b class="caret"></b></span> | |
</a> | |
<ul class="dropdown-menu"> | |
<!-- User image --> | |
<li {!! (Request::is('account/profile') ? ' class="active"' : '') !!}> | |
<a href="{{ route('view-assets') }}"> | |
<i class="fa fa-check fa-fw"></i> | |
{{ trans('general.viewassets') }} | |
</a></li> | |
<li {!! (Request::is('account/requested') ? ' class="active"' : '') !!}> | |
<a href="{{ route('account.requested') }}"> | |
<i class="fa fa-check fa-disk fa-fw"></i> | |
Requested Assets | |
</a></li> | |
<li> | |
<a href="{{ route('profile') }}"> | |
<i class="fa fa-user fa-fw"></i> | |
{{ trans('general.editprofile') }} | |
</a> | |
</li> | |
<li> | |
<a href="{{ route('account.password.index') }}"> | |
<i class="fa fa-asterisk fa-fw"></i> | |
{{ trans('general.changepassword') }} | |
</a> | |
</li> | |
@can('self.api') | |
<li> | |
<a href="{{ route('user.api') }}"> | |
<i class="fa fa-user-secret fa-fw"></i> Manage API Keys | |
</a> | |
</li> | |
@endcan | |
<li class="divider"></li> | |
<li> | |
<a href="{{ url('/logout') }}"> | |
<i class="fa fa-sign-out fa-fw"></i> | |
{{ trans('general.logout') }} | |
</a> | |
</li> | |
</ul> | |
</li> | |
@endif | |
@can('superadmin') | |
<li> | |
<a href="{{ route('settings.index') }}"> | |
<i class="fa fa-cogs fa-fw"></i> | |
</a> | |
</li> | |
@endcan | |
</ul> | |
</div> | |
</nav> | |
<a href="#" style="float:left" class="sidebar-toggle-mobile visible-xs btn" data-toggle="offcanvas" role="button"> | |
<span class="sr-only">Toggle navigation</span> | |
<i class="fa fa-bars"></i> | |
</a> | |
<!-- Sidebar toggle button--> | |
</header> | |
<!-- Left side column. contains the logo and sidebar --> | |
<aside class="main-sidebar"> | |
<!-- sidebar: style can be found in sidebar.less --> | |
<section class="sidebar"> | |
<!-- sidebar menu: : style can be found in sidebar.less --> | |
<ul class="sidebar-menu"> | |
@can('admin') | |
<li {!! (\Request::route()->getName()=='home' ? ' class="active"' : '') !!}> | |
<a href="{{ route('home') }}"> | |
<i class="fa fa-dashboard"></i> <span>Dashboard</span> | |
</a> | |
</li> | |
@endcan | |
@can('index', \App\Models\Asset::class) | |
<li class="treeview{{ (Request::is('hardware*') ? ' active' : '') }}"> | |
<a href="#"><i class="fa fa-barcode"></i> | |
<span>{{ trans('general.assets') }}</span> | |
<i class="fa fa-angle-left pull-right"></i> | |
</a> | |
<ul class="treeview-menu"> | |
<li> | |
<a href="{{ url('hardware') }}"> | |
{{ trans('general.list_all') }} | |
</a> | |
</li> | |
<?php $status_navs = \App\Models\Statuslabel::where('show_in_nav', '=', 1)->get(); ?> | |
@if (count($status_navs) > 0) | |
<li class="divider"> </li> | |
@foreach ($status_navs as $status_nav) | |
<li><a href="{{ route('statuslabels.show', ['id' => $status_nav->id]) }}"}> {{ $status_nav->name }}</a></li> | |
@endforeach | |
@endif | |
<li{!! (Request::query('status') == 'Deployed' ? ' class="active"' : '') !!}> | |
<a href="{{ url('hardware?status=Deployed') }}"><i class="fa fa-circle-o text-blue"></i> | |
{{ trans('general.all') }} | |
{{ trans('general.deployed') }} | |
</a> | |
</li> | |
<li{!! (Request::query('status') == 'RTD' ? ' class="active"' : '') !!}> | |
<a href="{{ url('hardware?status=RTD') }}"> | |
<i class="fa fa-circle-o text-green"></i> | |
{{ trans('general.all') }} | |
{{ trans('general.ready_to_deploy') }} | |
</a> | |
</li> | |
<li{!! (Request::query('status') == 'Pending' ? ' class="active"' : '') !!}><a href="{{ url('hardware?status=Pending') }}"><i class="fa fa-circle-o text-orange"></i> | |
{{ trans('general.all') }} | |
{{ trans('general.pending') }} | |
</a> | |
</li> | |
<li{!! (Request::query('status') == 'Undeployable' ? ' class="active"' : '') !!} ><a href="{{ url('hardware?status=Undeployable') }}"><i class="fa fa-times text-red"></i> | |
{{ trans('general.all') }} | |
{{ trans('general.undeployable') }} | |
</a> | |
</li> | |
<li{!! (Request::query('status') == 'Archived' ? ' class="active"' : '') !!}><a href="{{ url('hardware?status=Archived') }}"><i class="fa fa-times text-red"></i> | |
{{ trans('general.all') }} | |
{{ trans('admin/hardware/general.archived') }} | |
</a> | |
</li> | |
<li{!! (Request::query('status') == 'Requestable' ? ' class="active"' : '') !!}><a href="{{ url('hardware?status=Requestable') }}"><i class="fa fa-check text-blue"></i> | |
{{ trans('admin/hardware/general.requestable') }} | |
</a> | |
</li> | |
@can('audit', \App\Models\Asset::class) | |
<li{!! (Request::is('hardware/audit/due') ? ' class="active"' : '') !!}> | |
<a href="{{ route('assets.audit.due') }}"> | |
<i class="fa fa-clock-o text-yellow"></i> {{ trans('general.audit_due') }} | |
</a> | |
</li> | |
<li{!! (Request::is('hardware/audit/overdue') ? ' class="active"' : '') !!}> | |
<a href="{{ route('assets.audit.overdue') }}"> | |
<i class="fa fa-warning text-red"></i> {{ trans('general.audit_overdue') }} | |
</a> | |
</li> | |
@endcan | |
<li class="divider"> </li> | |
@can('checkout', \App\Models\Asset::class) | |
<li{!! (Request::is('hardware/bulkcheckout') ? ' class="active"' : '') !!}> | |
<a href="{{ route('hardware/bulkcheckout') }}"> | |
{{ trans('general.bulk_checkout') }} | |
</a> | |
</li> | |
<li{!! (Request::is('hardware/requested') ? ' class="active"' : '') !!}> | |
<a href="{{ route('assets.requested') }}"> | |
{{ trans('general.requested') }}</a> | |
</li> | |
@endcan | |
@can('create', \App\Models\Asset::class) | |
<li{!! (Request::query('Deleted') ? ' class="active"' : '') !!}> | |
<a href="{{ url('hardware?status=Deleted') }}"> | |
{{ trans('general.deleted') }} | |
</a> | |
</li> | |
<li> | |
<a href="{{ route('maintenances.index') }}"> | |
{{ trans('general.asset_maintenances') }} | |
</a> | |
</li> | |
<li> | |
<a href="{{ url('hardware/history') }}"> | |
{{ trans('general.import-history') }} | |
</a> | |
</li> | |
@endcan | |
@can('audit', \App\Models\Asset::class) | |
<li> | |
<a href="{{ route('assets.bulkaudit') }}"> | |
{{ trans('general.bulkaudit') }} | |
</a> | |
</li> | |
@endcan | |
</ul> | |
</li> | |
@endcan | |
@can('view', \App\Models\License::class) | |
<li{!! (Request::is('licenses*') ? ' class="active"' : '') !!}> | |
<a href="{{ route('licenses.index') }}"> | |
<i class="fa fa-floppy-o"></i> | |
<span>{{ trans('general.licenses') }}</span> | |
</a> | |
</li> | |
@endcan | |
@can('index', \App\Models\Accessory::class) | |
<li{!! (Request::is('accessories*') ? ' class="active"' : '') !!}> | |
<a href="{{ route('accessories.index') }}"> | |
<i class="fa fa-keyboard-o"></i> | |
<span>{{ trans('general.accessories') }}</span> | |
</a> | |
</li> | |
@endcan | |
@can('view', \App\Models\Consumable::class) | |
<li{!! (Request::is('consumables*') ? ' class="active"' : '') !!}> | |
<a href="{{ url('consumables') }}"> | |
<i class="fa fa-tint"></i> | |
<span>{{ trans('general.consumables') }}</span> | |
</a> | |
</li> | |
@endcan | |
@can('view', \App\Models\Component::class) | |
<li{!! (Request::is('components*') ? ' class="active"' : '') !!}> | |
<a href="{{ route('components.index') }}"> | |
<i class="fa fa-hdd-o"></i> | |
<span>{{ trans('general.components') }}</span> | |
</a> | |
</li> | |
@endcan | |
@can('view', \App\Models\User::class) | |
<li{!! (Request::is('users*') ? ' class="active"' : '') !!}> | |
<a href="{{ route('users.index') }}"> | |
<i class="fa fa-users"></i> | |
<span>{{ trans('general.people') }}</span> | |
</a> | |
</li> | |
@endcan | |
@can('import') | |
<li{!! (Request::is('import/*') ? ' class="active"' : '') !!}> | |
<a href="{{ route('imports.index') }}"> | |
<i class="fa fa-cloud-download"></i> | |
<span>{{ trans('general.import') }}</span> | |
</a> | |
</li> | |
@endcan | |
@can('backend.interact') | |
<li class="treeview"> | |
<a href="#"> | |
<i class="fa fa-gear"></i> | |
<span>{{ trans('general.settings') }}</span> | |
<i class="fa fa-angle-left pull-right"></i> | |
</a> | |
<ul class="treeview-menu"> | |
@if(Gate::allows('view', App\Models\CustomField::class) || Gate::allows('view', App\Models\CustomFieldset::class)) | |
<li {!! (Request::is('fields*') ? ' class="active"' : '') !!}> | |
<a href="{{ route('fields.index') }}"> | |
{{ trans('admin/custom_fields/general.custom_fields') }} | |
</a> | |
</li> | |
@endif | |
@can('view', \App\Models\Statuslabel::class) | |
<li {!! (Request::is('statuslabels*') ? ' class="active"' : '') !!}> | |
<a href="{{ route('statuslabels.index') }}"> | |
{{ trans('general.status_labels') }} | |
</a> | |
</li> | |
@endcan | |
@can('view', \App\Models\AssetModel::class) | |
<li> | |
<a href="{{ route('models.index') }}" {{ (Request::is('/assetmodels') ? ' class="active"' : '') }}> | |
{{ trans('general.asset_models') }} | |
</a> | |
</li> | |
@endcan | |
@can('view', \App\Models\Category::class) | |
<li> | |
<a href="{{ route('categories.index') }}" {{ (Request::is('/categories') ? ' class="active"' : '') }}> | |
{{ trans('general.categories') }} | |
</a> | |
</li> | |
@endcan | |
@can('view', \App\Models\Manufacturer::class) | |
<li> | |
<a href="{{ route('manufacturers.index') }}" {{ (Request::is('/manufacturers') ? ' class="active"' : '') }}> | |
{{ trans('general.manufacturers') }} | |
</a> | |
</li> | |
@endcan | |
@can('view', \App\Models\Supplier::class) | |
<li> | |
<a href="{{ route('suppliers.index') }}" {{ (Request::is('/suppliers') ? ' class="active"' : '') }}> | |
{{ trans('general.suppliers') }} | |
</a> | |
</li> | |
@endcan | |
@can('view', \App\Models\Department::class) | |
<li> | |
<a href="{{ route('departments.index') }}" {{ (Request::is('/departments') ? ' class="active"' : '') }}> | |
{{ trans('general.departments') }} | |
</a> | |
</li> | |
@endcan | |
@can('view', \App\Models\Location::class) | |
<li> | |
<a href="{{ route('locations.index') }}" {{ (Request::is('/locations') ? ' class="active"' : '') }}> | |
{{ trans('general.locations') }} | |
</a> | |
</li> | |
@endcan | |
@can('view', \App\Models\Company::class) | |
<li> | |
<a href="{{ route('companies.index') }}" {{ (Request::is('/companies') ? ' class="active"' : '') }}> | |
{{ trans('general.companies') }} | |
</a> | |
</li> | |
@endcan | |
@can('view', \App\Models\Depreciation::class) | |
<li> | |
<a href="{{ route('depreciations.index') }}" {{ (Request::is('/depreciations') ? ' class="active"' : '') }}> | |
{{ trans('general.depreciation') }} | |
</a> | |
</li> | |
@endcan | |
</ul> | |
</li> | |
@endcan | |
@can('reports.view') | |
<li class="treeview{{ (Request::is('reports*') ? ' active' : '') }}"> | |
<a href="#" class="dropdown-toggle"> | |
<i class="fa fa-bar-chart"></i> | |
<span>{{ trans('general.reports') }}</span> | |
<i class="fa fa-angle-left pull-right"></i> | |
</a> | |
<ul class="treeview-menu"> | |
<li> | |
<a href="{{ route('reports.activity') }}" {{ (Request::is('reports/activity') ? ' class="active"' : '') }}> | |
{{ trans('general.activity_report') }} | |
</a> | |
</li> | |
<li><a href="{{ route('reports.audit') }}" {{ (Request::is('reports.audit') ? ' class="active"' : '') }}> | |
{{ trans('general.audit_report') }}</a> | |
</li> | |
<li> | |
<a href="{{ url('reports/depreciation') }}" {{ (Request::is('reports/depreciation') ? ' class="active"' : '') }}> | |
{{ trans('general.depreciation_report') }} | |
</a> | |
</li> | |
<li> | |
<a href="{{ url('reports/licenses') }}" {{ (Request::is('reports/licenses') ? ' class="active"' : '') }}> | |
{{ trans('general.license_report') }} | |
</a> | |
</li> | |
<li> | |
<a href="{{ url('reports/asset_maintenances') }}" {{ (Request::is('reports/asset_maintenances') ? ' class="active"' : '') }}> | |
{{ trans('general.asset_maintenance_report') }} | |
</a> | |
</li> | |
<li> | |
<a href="{{ url('reports/unaccepted_assets') }}" {{ (Request::is('reports/unaccepted_assets') ? ' class="active"' : '') }}> | |
{{ trans('general.unaccepted_asset_report') }} | |
</a> | |
</li> | |
<li> | |
<a href="{{ url('reports/accessories') }}" {{ (Request::is('reports/accessories') ? ' class="active"' : '') }}> | |
{{ trans('general.accessory_report') }} | |
</a> | |
</li> | |
<li> | |
<a href="{{ url('reports/custom') }}" {{ (Request::is('reports/custom') ? ' class="active"' : '') }}> | |
{{ trans('general.custom_report') }} | |
</a> | |
</li> | |
</ul> | |
</li> | |
@endcan | |
@can('viewRequestable', \App\Models\Asset::class) | |
<li{!! (Request::is('account/requestable-assets') ? ' class="active"' : '') !!}> | |
<a href="{{ route('requestable-assets') }}"> | |
<i class="fa fa-laptop"></i> | |
<span>{{ trans('admin/hardware/general.requestable') }}</span> | |
</a> | |
</li> | |
@endcan | |
</ul> | |
</section> | |
<!-- /.sidebar --> | |
</aside> | |
<!-- Content Wrapper. Contains page content --> | |
<div class="content-wrapper"> | |
@if ($debug_in_production) | |
<div class="row" style="margin-bottom: 0px; background-color: red; color: white; font-size: 15px;"> | |
<div class="col-md-12" style="margin-bottom: 0px; background-color: #b50408 ; color: white; padding: 10px 20px 10px 30px; font-size: 16px;"> | |
<i class="fa fa-warning fa-3x pull-left"></i> <strong>{{ strtoupper(trans('general.debug_warning')) }}:</strong> | |
{!! trans('general.debug_warning_text') !!} | |
</div> | |
</div> | |
@endif | |
<!-- Content Header (Page header) --> | |
<section class="content-header" style="padding-bottom: 30px;"> | |
<h1 class="pull-left"> | |
@yield('title') | |
</h1> | |
<div class="pull-right"> | |
@yield('header_right') | |
</div> | |
</section> | |
<section class="content"> | |
<!-- Notifications --> | |
<div class="row"> | |
@if (config('app.lock_passwords')) | |
<div class="col-md-12"> | |
<div class="callout callout-info"> | |
{{ trans('general.some_features_disabled') }} | |
</div> | |
</div> | |
@endif | |
@include('notifications') | |
</div> | |
<!-- Content --> | |
<div id="{!! (Request::is('*api*') ? 'app' : 'webui') !!}"> | |
@yield('content') | |
</div> | |
</section> | |
</div><!-- /.content-wrapper --> | |
<footer class="main-footer hidden-print"> | |
<div class="pull-right hidden-xs"> | |
@if ($snipeSettings->version_footer!='off') | |
@if (($snipeSettings->version_footer=='on') || (($snipeSettings->version_footer=='admin') && (Auth::user()->isSuperUser()=='1'))) | |
<b>Version</b> {{ config('version.app_version') }} - build {{ config('version.build_version') }} ({{ config('version.branch') }}) | |
@endif | |
@endif | |
@if ($snipeSettings->support_footer!='off') | |
@if (($snipeSettings->support_footer=='on') || (($snipeSettings->support_footer=='admin') && (Auth::user()->isSuperUser()=='1'))) | |
<a target="_blank" class="btn btn-default btn-xs" href="https://snipe-it.readme.io/docs/overview" rel="noopener">User's Manual</a> | |
<a target="_blank" class="btn btn-default btn-xs" href="https://snipeitapp.com/support/" rel="noopener">Report a Bug</a> | |
@endif | |
@endif | |
@if ($snipeSettings->privacy_policy_link!='') | |
<a target="_blank" class="btn btn-default btn-xs" rel="noopener" href="{{ $snipeSettings->privacy_policy_link }}" target="_new">{{ trans('admin/settings/general.privacy_policy') }}</a> | |
@endif | |
</div> | |
@if ($snipeSettings->footer_text!='') | |
<div class="pull-right"> | |
{!! Parsedown::instance()->text(e($snipeSettings->footer_text)) !!} | |
</div> | |
@endif | |
<a target="_blank" href="https://snipeitapp.com" rel="noopener">Snipe-IT</a> is open source software, made with <i class="fa fa-heart" style="color: #a94442; font-size: 10px"></i> by <a href="https://twitter.com/snipeitapp" rel="noopener">@snipeitapp</a>. | |
</footer> | |
</div><!-- ./wrapper --> | |
<!-- end main container --> | |
<div class="modal modal-danger fade" id="dataConfirmModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> | |
<div class="modal-dialog"> | |
<div class="modal-content"> | |
<div class="modal-header"> | |
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> | |
<h4 class="modal-title" id="myModalLabel"></h4> | |
</div> | |
<div class="modal-body"></div> | |
<div class="modal-footer"> | |
<form method="post" id="deleteForm" role="form"> | |
{{ csrf_field() }} | |
{{ method_field('DELETE') }} | |
<button type="button" class="btn btn-default pull-left" data-dismiss="modal">{{ trans('general.cancel') }}</button> | |
<button type="submit" class="btn btn-outline" id="dataConfirmOK">{{ trans('general.yes') }}</button> | |
</form> | |
</div> | |
</div> | |
</div> | |
</div> | |
<script src="{{ url(mix('js/dist/all.js')) }}" nonce="{{ csrf_token() }}"></script> | |
@section('moar_scripts') | |
@show | |
<script nonce="{{ csrf_token() }}"> | |
$(function () { | |
$('[data-toggle="tooltip"]').tooltip(); | |
$('.select2 span').addClass('needsclick'); | |
// This javascript handles saving the state of the menu (expanded or not) | |
$('body').bind('expanded.pushMenu', function() { | |
$.ajax({ | |
type: 'GET', | |
url: "{{ route('account.menuprefs', ['state'=>'open']) }}", | |
_token: "{{ csrf_token() }}" | |
}); | |
}); | |
$('body').bind('collapsed.pushMenu', function() { | |
$.ajax({ | |
type: 'GET', | |
url: "{{ route('account.menuprefs', ['state'=>'close']) }}", | |
_token: "{{ csrf_token() }}" | |
}); | |
}); | |
}); | |
// Initiate the ekko lightbox | |
$(document).on('click', '[data-toggle="lightbox"]', function(event) { | |
event.preventDefault(); | |
$(this).ekkoLightbox(); | |
}); | |
</script> | |
@if ((Session::get('topsearch')=='true') || (Request::is('/'))) | |
<script nonce="{{ csrf_token() }}"> | |
$("#tagSearch").focus(); | |
</script> | |
@endif | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment