mirror of
https://github.com/snipe/snipe-it.git
synced 2024-11-11 08:04:09 -08:00
Merge branch 'develop'
This commit is contained in:
commit
cfc215a013
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -27,6 +27,7 @@ public/uploads/logo.png
|
|||
public/uploads/logo.svg
|
||||
public/uploads/models/*
|
||||
public/uploads/suppliers/*
|
||||
public/uploads/accessories/*
|
||||
public/uploads/users/*
|
||||
storage/app/private_uploads/users/*
|
||||
storage/debugbar/
|
||||
|
|
|
@ -7,6 +7,6 @@ class CheckoutNotAllowed extends Exception
|
|||
{
|
||||
public function __toString()
|
||||
{
|
||||
"A checkout is not allowed under these circumstances";
|
||||
return "A checkout is not allowed under these circumstances";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ use Illuminate\Http\Request;
|
|||
use Slack;
|
||||
use Str;
|
||||
use View;
|
||||
use Image;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
|
||||
/** This controller handles all actions related to Accessories for
|
||||
* the Snipe-IT Asset Management application.
|
||||
|
@ -57,6 +59,7 @@ class AccessoriesController extends Controller
|
|||
->with('item', new Accessory)
|
||||
->with('category_list', Helper::categoryList('accessory'))
|
||||
->with('company_list', Helper::companyList())
|
||||
->with('supplier_list', Helper::suppliersList())
|
||||
->with('location_list', Helper::locationsList())
|
||||
->with('manufacturer_list', Helper::manufacturerList());
|
||||
}
|
||||
|
@ -68,7 +71,7 @@ class AccessoriesController extends Controller
|
|||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @return Redirect
|
||||
*/
|
||||
public function store(Request $request)
|
||||
public function store(ImageUploadRequest $request)
|
||||
{
|
||||
$this->authorize(Accessory::class);
|
||||
// create a new model instance
|
||||
|
@ -87,6 +90,28 @@ class AccessoriesController extends Controller
|
|||
$accessory->purchase_cost = Helper::ParseFloat(request('purchase_cost'));
|
||||
$accessory->qty = request('qty');
|
||||
$accessory->user_id = Auth::user()->id;
|
||||
$accessory->supplier_id = request('supplier_id');
|
||||
|
||||
if ($request->hasFile('image')) {
|
||||
|
||||
if (!config('app.lock_passwords')) {
|
||||
$image = $request->file('image');
|
||||
$ext = $image->getClientOriginalExtension();
|
||||
$file_name = "accessory-".str_random(18).'.'.$ext;
|
||||
$path = public_path('/uploads/accessories');
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(null, 250, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path.'/'.$file_name);
|
||||
} else {
|
||||
$image->move($path, $file_name);
|
||||
}
|
||||
$accessory->image = $file_name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Was the accessory created?
|
||||
if ($accessory->save()) {
|
||||
|
@ -116,6 +141,7 @@ class AccessoriesController extends Controller
|
|||
->with('category_list', Helper::categoryList('accessory'))
|
||||
->with('company_list', Helper::companyList())
|
||||
->with('location_list', Helper::locationsList())
|
||||
->with('supplier_list', Helper::suppliersList())
|
||||
->with('manufacturer_list', Helper::manufacturerList());
|
||||
}
|
||||
|
||||
|
@ -127,7 +153,7 @@ class AccessoriesController extends Controller
|
|||
* @param int $accessoryId
|
||||
* @return Redirect
|
||||
*/
|
||||
public function update(Request $request, $accessoryId = null)
|
||||
public function update(ImageUploadRequest $request, $accessoryId = null)
|
||||
{
|
||||
if (is_null($accessory = Accessory::find($accessoryId))) {
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
|
||||
|
@ -144,11 +170,38 @@ class AccessoriesController extends Controller
|
|||
$accessory->manufacturer_id = request('manufacturer_id');
|
||||
$accessory->order_number = request('order_number');
|
||||
$accessory->model_number = request('model_number');
|
||||
$accessory->purchase_date = request('purchase_date');
|
||||
$accessory->purchase_cost = request('purchase_cost');
|
||||
$accessory->purchase_date = request('purchase_date');
|
||||
$accessory->purchase_cost = request('purchase_cost');
|
||||
$accessory->qty = request('qty');
|
||||
$accessory->supplier_id = request('supplier_id');
|
||||
|
||||
// Was the accessory updated?
|
||||
if ($request->hasFile('image')) {
|
||||
|
||||
if (!config('app.lock_passwords')) {
|
||||
|
||||
|
||||
$image = $request->file('image');
|
||||
$ext = $image->getClientOriginalExtension();
|
||||
$file_name = "accessory-".str_random(18).'.'.$ext;
|
||||
$path = public_path('/uploads/accessories');
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(null, 250, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path.'/'.$file_name);
|
||||
} else {
|
||||
$image->move($path, $file_name);
|
||||
}
|
||||
if (($accessory->image) && (file_exists($path.'/'.$accessory->image))) {
|
||||
unlink($path.'/'.$accessory->image);
|
||||
}
|
||||
|
||||
$accessory->image = $file_name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Was the accessory updated?
|
||||
if ($accessory->save()) {
|
||||
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.update.success'));
|
||||
}
|
||||
|
|
|
@ -38,6 +38,10 @@ class AccessoriesController extends Controller
|
|||
$accessories->where('manufacturer_id','=',$request->input('manufacturer_id'));
|
||||
}
|
||||
|
||||
if ($request->has('supplier_id')) {
|
||||
$accessories->where('supplier_id','=',$request->input('supplier_id'));
|
||||
}
|
||||
|
||||
$offset = $request->input('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
|
|
@ -457,16 +457,28 @@ class AssetsController extends Controller
|
|||
|
||||
$this->authorize('checkout', $asset);
|
||||
|
||||
$error_payload = [];
|
||||
$error_payload['asset'] = [
|
||||
'id' => $asset->id,
|
||||
'asset_tag' => $asset->asset_tag,
|
||||
];
|
||||
if ($request->has('user_id')) {
|
||||
$target = User::find($request->input('user_id'));
|
||||
$error_payload['target_id'] = $request->input('user_id');
|
||||
$error_payload['target_type'] = User::class;
|
||||
// Don't let the user check an asset out to itself
|
||||
} elseif ($request->has('asset_id')) {
|
||||
$target = Asset::find($request->input('asset_id'));
|
||||
$target = Asset::where('id','!=',$asset_id)->find($request->input('asset_id'));
|
||||
$error_payload['target_id'] = $request->input('asset_id');
|
||||
$error_payload['target_type'] = Asset::class;
|
||||
} elseif ($request->has('location_id')) {
|
||||
$target = Location::find($request->input('location_id'));
|
||||
$error_payload['target_id'] = $request->input('location_id');
|
||||
$error_payload['target_type'] = Location::class;
|
||||
}
|
||||
|
||||
if (!isset($target)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', ['asset'=> e($asset->asset_tag)], 'No valid checkout target specified for asset '.e($asset->asset_tag).'.'));
|
||||
return response()->json(Helper::formatStandardApiResponse('error', $error_payload, 'No valid checkout target specified for asset '.e($asset->asset_tag).'.'));
|
||||
}
|
||||
|
||||
$checkout_at = request('checkout_at', date("Y-m-d H:i:s"));
|
||||
|
|
|
@ -20,7 +20,7 @@ class CategoriesController extends Controller
|
|||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('view', Category::class);
|
||||
$allowed_columns = ['id', 'name','category_type','use_default_eula','eula_text', 'require_acceptance','checkin_email'];
|
||||
$allowed_columns = ['id', 'name','category_type','use_default_eula','eula_text', 'require_acceptance','checkin_email', 'assets_count', 'accessories_count', 'consumables_count', 'components_count'];
|
||||
|
||||
$categories = Category::select(['id', 'created_at', 'updated_at', 'name','category_type','use_default_eula','eula_text', 'require_acceptance','checkin_email'])
|
||||
->withCount('assets', 'accessories', 'consumables', 'components');
|
||||
|
@ -32,7 +32,7 @@ class CategoriesController extends Controller
|
|||
$offset = $request->input('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'assets_count';
|
||||
$categories->orderBy($sort, $order);
|
||||
|
||||
$total = $categories->count();
|
||||
|
|
|
@ -22,7 +22,7 @@ class StatuslabelsController extends Controller
|
|||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('view', Statuslabel::class);
|
||||
$allowed_columns = ['id','name','created_at'];
|
||||
$allowed_columns = ['id','name','created_at', 'assets_count'];
|
||||
|
||||
$statuslabels = Statuslabel::withCount('assets');
|
||||
|
||||
|
@ -137,8 +137,14 @@ class StatuslabelsController extends Controller
|
|||
$this->authorize('delete', Statuslabel::class);
|
||||
$statuslabel = Statuslabel::findOrFail($id);
|
||||
$this->authorize('delete', $statuslabel);
|
||||
$statuslabel->delete();
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/statuslabels/message.delete.success')));
|
||||
|
||||
// Check that there are no assets associated
|
||||
if ($statuslabel->assets()->count() == 0) {
|
||||
$statuslabel->delete();
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/statuslabels/message.delete.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/statuslabels/message.assoc_assets')));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -20,11 +20,11 @@ class SuppliersController extends Controller
|
|||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('view', Supplier::class);
|
||||
$allowed_columns = ['id','name','address','phone','contact','fax','email'];
|
||||
$allowed_columns = ['id','name','address','phone','contact','fax','email','image','assets_count','licenses_count', 'accessories_count'];
|
||||
|
||||
$suppliers = Supplier::select(
|
||||
array('id','name','address','address2','city','state','country','fax', 'phone','email','contact','created_at','updated_at','deleted_at')
|
||||
)->withCount('assets')->withCount('licenses')->whereNull('deleted_at');
|
||||
)->withCount('assets')->withCount('licenses')->withCount('accessories')->whereNull('deleted_at');
|
||||
|
||||
|
||||
if ($request->has('search')) {
|
||||
|
|
|
@ -458,7 +458,7 @@ class AssetsController extends Controller
|
|||
if (request('assigned_user')) {
|
||||
$target = User::find(request('assigned_user'));
|
||||
} elseif (request('assigned_asset')) {
|
||||
$target = Asset::find(request('assigned_asset'));
|
||||
$target = Asset::where('id','!=',$assetId)->find(request('assigned_asset'));
|
||||
} elseif (request('assigned_location')) {
|
||||
$target = Location::find(request('assigned_location'));
|
||||
}
|
||||
|
|
|
@ -826,6 +826,7 @@ class SettingsController extends Controller
|
|||
$setting->is_ad = $request->input('is_ad', '0');
|
||||
$setting->ldap_tls = $request->input('ldap_tls', '0');
|
||||
$setting->ldap_pw_sync = $request->input('ldap_pw_sync', '0');
|
||||
$setting->custom_forgot_pass_url = $request->input('custom_forgot_pass_url');
|
||||
|
||||
if ($setting->save()) {
|
||||
return redirect()->route('settings.index')
|
||||
|
|
|
@ -200,17 +200,15 @@ class StatuslabelsController extends Controller
|
|||
{
|
||||
// Check if the Statuslabel exists
|
||||
if (is_null($statuslabel = Statuslabel::find($statuslabelId))) {
|
||||
// Redirect to the blogs management page
|
||||
return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.not_found'));
|
||||
}
|
||||
|
||||
|
||||
if ($statuslabel->has_assets() == 0) {
|
||||
// Check that there are no assets associated
|
||||
if ($statuslabel->assets()->count() == 0) {
|
||||
$statuslabel->delete();
|
||||
// Redirect to the statuslabels management page
|
||||
return redirect()->route('statuslabels.index')->with('success', trans('admin/statuslabels/message.delete.success'));
|
||||
}
|
||||
// Redirect to the asset management page
|
||||
|
||||
return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.assoc_assets'));
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ use Str;
|
|||
use View;
|
||||
use Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
|
||||
|
@ -56,7 +57,7 @@ class SuppliersController extends Controller
|
|||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(Request $request)
|
||||
public function store(ImageUploadRequest $request)
|
||||
{
|
||||
// Create a new supplier
|
||||
$supplier = new Supplier;
|
||||
|
@ -135,7 +136,7 @@ class SuppliersController extends Controller
|
|||
* @param int $supplierId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update($supplierId = null, Request $request)
|
||||
public function update($supplierId = null, ImageUploadRequest $request)
|
||||
{
|
||||
// Check if the supplier exists
|
||||
if (is_null($supplier = Supplier::find($supplierId))) {
|
||||
|
@ -158,18 +159,17 @@ class SuppliersController extends Controller
|
|||
$supplier->url = $supplier->addhttp(request('url'));
|
||||
$supplier->notes = request('notes');
|
||||
|
||||
|
||||
if (Input::file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = str_random(25).".".$image->getClientOriginalExtension();
|
||||
$file_name = 'suppliers-'.str_random(25).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/suppliers/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(300, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$supplier->image = $file_name;
|
||||
}
|
||||
|
||||
if (request('image_delete') == 1 && $request->file('image') == "") {
|
||||
} elseif (request('image_delete') == 1) {
|
||||
$supplier->image = null;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,10 +23,13 @@ class AssetCheckoutRequest extends Request
|
|||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
$rules = [
|
||||
"assigned_user" => 'required_without_all:assigned_asset,assigned_location',
|
||||
"assigned_asset" => 'required_without_all:assigned_user,assigned_location',
|
||||
"assigned_asset" => 'required_without_all:assigned_user,assigned_location|different:'.$this->id,
|
||||
"assigned_location" => 'required_without_all:assigned_user,assigned_asset',
|
||||
];
|
||||
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ class AccessoriesTransformer
|
|||
'name' => e($accessory->name),
|
||||
'company' => ($accessory->company) ? ['id' => $accessory->company->id,'name'=> e($accessory->company->name)] : null,
|
||||
'manufacturer' => ($accessory->manufacturer) ? ['id' => $accessory->manufacturer->id,'name'=> e($accessory->manufacturer->name)] : null,
|
||||
'supplier' => ($accessory->supplier) ? ['id' => $accessory->supplier->id,'name'=> e($accessory->supplier->name)] : null,
|
||||
'model_number' => ($accessory->model_number) ? e($accessory->model_number) : null,
|
||||
'category' => ($accessory->category) ? ['id' => $accessory->category->id,'name'=> e($accessory->category->name)] : null,
|
||||
'location' => ($accessory->location) ? ['id' => $accessory->location->id,'name'=> e($accessory->location->name)] : null,
|
||||
|
@ -35,6 +36,7 @@ class AccessoriesTransformer
|
|||
'order_number' => ($accessory->order_number) ? e($accessory->order_number) : null,
|
||||
'min_qty' => ($accessory->min_amt) ? (int) $accessory->min_amt : null,
|
||||
'remaining_qty' => $accessory->numRemaining(),
|
||||
'image' => ($accessory->image) ? url('/').'/uploads/accessories/'.e($accessory->image) : null,
|
||||
'created_at' => Helper::getFormattedDateObject($accessory->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($accessory->updated_at, 'datetime'),
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ class CategoriesTransformer
|
|||
|
||||
$permissions_array['available_actions'] = [
|
||||
'update' => Gate::allows('update', Category::class) ? true : false,
|
||||
'delete' => Gate::allows('delete', Category::class) ? true : false,
|
||||
'delete' => (Gate::allows('delete', Category::class) && ($category->assets_count == 0) && ($category->accessories_count == 0) && ($category->consumables_count == 0) && ($category->components_count == 0)) ? true : false,
|
||||
];
|
||||
|
||||
$array += $permissions_array;
|
||||
|
|
|
@ -26,6 +26,7 @@ class StatuslabelsTransformer
|
|||
'type' => $statuslabel->getStatuslabelType(),
|
||||
'color' => ($statuslabel->color) ? e($statuslabel->color) : null,
|
||||
'show_in_nav' => ($statuslabel->show_in_nav=='1') ? true : false,
|
||||
'assets_count' => (int) $statuslabel->assets_count,
|
||||
'notes' => e($statuslabel->notes),
|
||||
'created_at' => Helper::getFormattedDateObject($statuslabel->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($statuslabel->updated_at, 'datetime'),
|
||||
|
@ -33,7 +34,7 @@ class StatuslabelsTransformer
|
|||
|
||||
$permissions_array['available_actions'] = [
|
||||
'update' => Gate::allows('update', Statuslabel::class) ? true : false,
|
||||
'delete' => Gate::allows('delete', Statuslabel::class) ? true : false,
|
||||
'delete' => (Gate::allows('delete', Statuslabel::class) && ($statuslabel->assets_count == 0)) ? true : false,
|
||||
];
|
||||
$array += $permissions_array;
|
||||
|
||||
|
|
|
@ -36,8 +36,9 @@ class SuppliersTransformer
|
|||
'email' => ($supplier->email) ? e($supplier->email) : null,
|
||||
'contact' => ($supplier->contact) ? e($supplier->contact) : null,
|
||||
'assets_count' => (int) $supplier->assets_count,
|
||||
'accessories_count' => (int) $supplier->accessories_count,
|
||||
'licenses_count' => (int) $supplier->licenses_count,
|
||||
'image' => ($supplier->image) ? e($supplier->image) : null,
|
||||
'image' => ($supplier->image) ? url('/').'/uploads/suppliers/'.e($supplier->image) : null,
|
||||
'notes' => ($supplier->notes) ? e($supplier->notes) : null,
|
||||
'created_at' => Helper::getFormattedDateObject($supplier->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($supplier->updated_at, 'datetime'),
|
||||
|
@ -46,7 +47,7 @@ class SuppliersTransformer
|
|||
|
||||
$permissions_array['available_actions'] = [
|
||||
'update' => Gate::allows('update', Supplier::class) ? true : false,
|
||||
'delete' => Gate::allows('delete', Supplier::class) ? true : false,
|
||||
'delete' => (Gate::allows('delete', Supplier::class) && ($supplier->assets_count == 0) && ($supplier->licenses_count == 0) && ($supplier->accessories_count == 0)) ? true : false,
|
||||
];
|
||||
|
||||
$array += $permissions_array;
|
||||
|
|
|
@ -17,7 +17,7 @@ class Accessory extends SnipeModel
|
|||
use Loggable, Presentable;
|
||||
use SoftDeletes;
|
||||
|
||||
protected $dates = ['deleted_at', 'purchase_date'];
|
||||
protected $dates = ['deleted_at'];
|
||||
protected $table = 'accessories';
|
||||
protected $casts = [
|
||||
'requestable' => 'boolean'
|
||||
|
@ -61,10 +61,19 @@ class Accessory extends SnipeModel
|
|||
'purchase_date',
|
||||
'model_number',
|
||||
'manufacturer_id',
|
||||
'supplier_id',
|
||||
'image',
|
||||
'qty',
|
||||
'requestable'
|
||||
];
|
||||
|
||||
|
||||
public function supplier()
|
||||
{
|
||||
return $this->belongsTo('\App\Models\Supplier', 'supplier_id');
|
||||
}
|
||||
|
||||
|
||||
public function setRequestableAttribute($value)
|
||||
{
|
||||
if ($value == '') {
|
||||
|
|
|
@ -38,6 +38,7 @@ class Setting extends Model
|
|||
"pwd_secure_min" => "numeric|required|min:5",
|
||||
"audit_warning_days" => "numeric|nullable",
|
||||
"audit_interval" => "numeric|nullable",
|
||||
"custom_forgot_pass_url" => "url|nullable",
|
||||
];
|
||||
|
||||
protected $fillable = ['site_name','email_domain','email_format','username_format'];
|
||||
|
|
|
@ -29,16 +29,6 @@ class Statuslabel extends SnipeModel
|
|||
|
||||
protected $fillable = ['name', 'deployable', 'pending', 'archived'];
|
||||
|
||||
/**
|
||||
* Show count of assets with status label
|
||||
*
|
||||
* @todo Remove this. It's dumb.
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function has_assets()
|
||||
{
|
||||
return $this->hasMany('\App\Models\Asset', 'status_id')->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get assets with associated status label
|
||||
|
@ -64,6 +54,27 @@ class Statuslabel extends SnipeModel
|
|||
}
|
||||
}
|
||||
|
||||
public function scopePending()
|
||||
{
|
||||
return $this->where('pending', '=', 1)
|
||||
->where('archived', '=', 0)
|
||||
->where('deployable', '=', 0);
|
||||
}
|
||||
|
||||
public function scopeArchived()
|
||||
{
|
||||
return $this->where('pending', '=', 0)
|
||||
->where('archived', '=', 1)
|
||||
->where('deployable', '=', 0);
|
||||
}
|
||||
|
||||
public function scopeDeployable()
|
||||
{
|
||||
return $this->where('pending', '=', 0)
|
||||
->where('archived', '=', 0)
|
||||
->where('deployable', '=', 1);
|
||||
}
|
||||
|
||||
|
||||
public static function getStatuslabelTypesForDB($type)
|
||||
{
|
||||
|
|
|
@ -68,6 +68,11 @@ class Supplier extends SnipeModel
|
|||
return $this->hasMany('\App\Models\Asset', 'supplier_id');
|
||||
}
|
||||
|
||||
public function accessories()
|
||||
{
|
||||
return $this->hasMany('\App\Models\Accessory', 'supplier_id');
|
||||
}
|
||||
|
||||
public function asset_maintenances()
|
||||
{
|
||||
return $this->hasMany('\App\Models\AssetMaintenance', 'supplier_id');
|
||||
|
|
|
@ -31,6 +31,14 @@ class AccessoryPresenter extends Presenter
|
|||
"switchable" => true,
|
||||
"title" => trans('general.id'),
|
||||
"visible" => false
|
||||
],[
|
||||
"field" => "image",
|
||||
"searchable" => false,
|
||||
"sortable" => true,
|
||||
"switchable" => true,
|
||||
"title" => trans('admin/hardware/table.image'),
|
||||
"visible" => true,
|
||||
"formatter" => "imageFormatter"
|
||||
], [
|
||||
"field" => "company",
|
||||
"searchable" => true,
|
||||
|
@ -63,6 +71,14 @@ class AccessoryPresenter extends Presenter
|
|||
"sortable" => true,
|
||||
"title" => trans('general.manufacturer'),
|
||||
"formatter" => "manufacturersLinkObjFormatter",
|
||||
], [
|
||||
"field" => "supplier",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"switchable" => true,
|
||||
"title" => trans('general.supplier'),
|
||||
"visible" => false,
|
||||
"formatter" => "suppliersLinkObjFormatter"
|
||||
], [
|
||||
"field" => "location",
|
||||
"searchable" => true,
|
||||
|
|
|
@ -41,25 +41,25 @@ class CategoryPresenter extends Presenter
|
|||
], [
|
||||
"field" => "assets_count",
|
||||
"searchable" => false,
|
||||
"sortable" => false,
|
||||
"sortable" => true,
|
||||
"title" => trans('general.assets'),
|
||||
"visible" => true
|
||||
], [
|
||||
"field" => "accessories_count",
|
||||
"searchable" => false,
|
||||
"sortable" => false,
|
||||
"sortable" => true,
|
||||
"title" => trans('general.accessories'),
|
||||
"visible" => true
|
||||
], [
|
||||
"field" => "consumables_count",
|
||||
"searchable" => false,
|
||||
"sortable" => false,
|
||||
"sortable" => true,
|
||||
"title" => trans('general.consumables'),
|
||||
"visible" => true
|
||||
], [
|
||||
"field" => "components_count",
|
||||
"searchable" => false,
|
||||
"sortable" => false,
|
||||
"sortable" => true,
|
||||
"title" => trans('general.components'),
|
||||
"visible" => true
|
||||
], [
|
||||
|
@ -72,7 +72,7 @@ class CategoryPresenter extends Presenter
|
|||
], [
|
||||
"field" => "require_acceptance",
|
||||
"searchable" => false,
|
||||
"sortable" => false,
|
||||
"sortable" => true,
|
||||
"title" => trans('admin/categories/table.require_acceptance'),
|
||||
"visible" => true,
|
||||
"formatter" => 'trueFalseFormatter',
|
||||
|
|
|
@ -24,7 +24,8 @@ $factory->state(App\Models\Accessory::class, 'apple-bt-keyboard', function ($fak
|
|||
'category_id' => 8,
|
||||
'manufacturer_id' => 1,
|
||||
'qty' => 10,
|
||||
'min_amt' => 2
|
||||
'min_amt' => 2,
|
||||
'supplier_id' => rand(1,5)
|
||||
];
|
||||
|
||||
});
|
||||
|
@ -36,7 +37,8 @@ $factory->state(App\Models\Accessory::class, 'apple-usb-keyboard', function ($fa
|
|||
'category_id' => 8,
|
||||
'manufacturer_id' => 1,
|
||||
'qty' => 15,
|
||||
'min_amt' => 2
|
||||
'min_amt' => 2,
|
||||
'supplier_id' => rand(1,5)
|
||||
];
|
||||
|
||||
});
|
||||
|
@ -48,7 +50,8 @@ $factory->state(App\Models\Accessory::class, 'apple-mouse', function ($faker) {
|
|||
'category_id' => 9,
|
||||
'manufacturer_id' => 1,
|
||||
'qty' => 13,
|
||||
'min_amt' => 2
|
||||
'min_amt' => 2,
|
||||
'supplier_id' => rand(1,5)
|
||||
];
|
||||
|
||||
});
|
||||
|
@ -56,7 +59,7 @@ $factory->state(App\Models\Accessory::class, 'apple-mouse', function ($faker) {
|
|||
$factory->state(App\Models\Accessory::class, 'microsoft-mouse', function ($faker) {
|
||||
|
||||
return [
|
||||
'name' => 'Sculpt Comfort Mouse\'',
|
||||
'name' => 'Sculpt Comfort Mouse',
|
||||
'category_id' => 9,
|
||||
'manufacturer_id' => 2,
|
||||
'qty' => 13,
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddCustomForgotPasswordUrl extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->string('custom_forgot_pass_url')->nullable()->default(null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->dropColumn('custom_forgot_pass_url');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddImageAndSupplierToAccessories extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('accessories', function (Blueprint $table) {
|
||||
$table->string('image')->nullable()->default(null);
|
||||
$table->integer('supplier_id')->nullable()->default(null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('accessories', function (Blueprint $table) {
|
||||
$table->dropColumn('image');
|
||||
$table->dropColumn('supplier_id');
|
||||
});
|
||||
}
|
||||
}
|
1
public/uploads/accessories/.gitignore
vendored
Executable file
1
public/uploads/accessories/.gitignore
vendored
Executable file
|
@ -0,0 +1 @@
|
|||
!.gitignore
|
0
public/uploads/accessories/.gitkeep
Executable file
0
public/uploads/accessories/.gitkeep
Executable file
|
@ -23,6 +23,8 @@ return array(
|
|||
'confirm_purge_help' => 'Enter the text "DELETE" in the box below to purge your deleted records. This action cannot be undone.',
|
||||
'custom_css' => 'Custom CSS',
|
||||
'custom_css_help' => 'Enter any custom CSS overrides you would like to use. Do not include the <style></style> tags.',
|
||||
'custom_forgot_pass_url' => 'Custom Password Reset URL',
|
||||
'custom_forgot_pass_url_help' => 'This replaces the built-in forgotten password URL on the login screen, useful to direct people to internal or hosted LDAP password reset functionality. It will effectively disable local user forgotten password functionality.',
|
||||
'default_currency' => 'Default Currency',
|
||||
'default_eula_text' => 'Default EULA',
|
||||
'default_language' => 'Default Language',
|
||||
|
@ -44,6 +46,8 @@ return array(
|
|||
'ldap_enabled' => 'LDAP enabled',
|
||||
'ldap_integration' => 'LDAP Integration',
|
||||
'ldap_settings' => 'LDAP Settings',
|
||||
'ldap_login_test_help' => 'Enter a valid LDAP username and password to test whether your LDAP login is configured correctly.',
|
||||
'ldap_login_sync_help' => 'This only tests that LDAP can sync correctly. If your LDAP Authentication query is not correct, users may still not be able to login.',
|
||||
'ldap_server' => 'LDAP Server',
|
||||
'ldap_server_help' => 'This should start with ldap:// (for unencrypted or TLS) or ldaps:// (for SSL)',
|
||||
'ldap_server_cert' => 'LDAP SSL certificate validation',
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
@include ('partials.forms.edit.company')
|
||||
@include ('partials.forms.edit.name', ['translated_name' => trans('admin/accessories/general.accessory_name')])
|
||||
@include ('partials.forms.edit.category')
|
||||
@include ('partials.forms.edit.supplier')
|
||||
@include ('partials.forms.edit.manufacturer')
|
||||
@include ('partials.forms.edit.location')
|
||||
@include ('partials.forms.edit.model_number')
|
||||
|
@ -21,4 +22,20 @@
|
|||
@include ('partials.forms.edit.quantity')
|
||||
@include ('partials.forms.edit.minimum_quantity')
|
||||
|
||||
<!-- Image -->
|
||||
|
||||
<div class="form-group {{ $errors->has('image') ? ' has-error' : '' }}">
|
||||
{{ Form::label('image', trans('general.image_upload'), array('class' => 'col-md-3 control-label')) }}
|
||||
<div class="col-md-7">
|
||||
@if (config('app.lock_passwords'))
|
||||
<p class="help-block">{{ trans('general.lock_passwords') }}</p>
|
||||
@else
|
||||
{{ Form::file('image') }}
|
||||
{!! $errors->first('image', '<span class="alert-msg">:message</span>') !!}
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@stop
|
||||
|
|
|
@ -63,7 +63,13 @@
|
|||
<button class="btn btn-lg btn-primary btn-block">{{ trans('auth/general.login') }}</button>
|
||||
</div>
|
||||
<div class="col-md-12 col-sm-12 col-xs-12 text-right" style="padding-top: 10px;">
|
||||
<a href="{{ route('password.request') }}">{{ trans('auth/general.forgot_password') }}</a>
|
||||
@if ($snipeSettings->custom_forgot_pass_url)
|
||||
<a href="{{ $snipeSettings->custom_forgot_pass_url }}" rel="noopener">{{ trans('auth/general.forgot_password') }}</a>
|
||||
@else
|
||||
<a href="{{ route('password.request') }}">{{ trans('auth/general.forgot_password') }}</a>
|
||||
@endif
|
||||
|
||||
|
||||
</div>
|
||||
</div> <!-- end login box -->
|
||||
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
|
||||
{{-- Page content --}}
|
||||
@section('content')
|
||||
|
||||
@if ($snipeSettings->custom_forgot_pass_url)
|
||||
<a href="{{ $snipeSettings->custom_forgot_pass_url }}" rel="noopener">{{ trans('auth/general.forgot_password') }}</a>
|
||||
@else
|
||||
|
||||
<form class="form" role="form" method="POST" action="{{ url('/password/email') }}">
|
||||
{!! csrf_field() !!}
|
||||
<div class="container">
|
||||
|
@ -50,5 +55,7 @@
|
|||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
@endif
|
||||
@stop
|
||||
|
||||
|
|
|
@ -198,12 +198,16 @@ $('.snipe-table').bootstrapTable({
|
|||
+ ' 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>';
|
||||
+ '<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;
|
||||
|
||||
};
|
||||
|
|
|
@ -334,9 +334,9 @@
|
|||
|
||||
@if ($setting->ldap_enabled)
|
||||
<!-- LDAP test -->
|
||||
<div class="form-group {{ $errors->has('ldap_email') ? 'error' : '' }}">
|
||||
<div class="form-group">
|
||||
<div class="col-md-3">
|
||||
Test LDAP Sync
|
||||
{{ Form::label('test_ldap_sync', 'Test LDAP Sync') }}
|
||||
</div>
|
||||
<div class="col-md-9" id="ldaptestrow">
|
||||
<a class="btn btn-default btn-sm pull-left" id="ldaptest" style="margin-right: 10px;">Test LDAP</a>
|
||||
|
@ -347,14 +347,14 @@
|
|||
<span id="ldapteststatus"></span>
|
||||
</div>
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
<p class="help-block">This only tests that LDAP can sync correctly. If your LDAP Authentication query is not correct, users may still not be able to login.</p>
|
||||
<p class="help-block">{{ trans('admin/settings/general.ldap_login_sync_help') }}</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- LDAP Login test -->
|
||||
<div class="form-group {{ $errors->has('ldap_email') ? 'error' : '' }}">
|
||||
<div class="form-group">
|
||||
<div class="col-md-3">
|
||||
Test LDAP Login
|
||||
{{ Form::label('test_ldap_login', 'Test LDAP Login') }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<div class="row">
|
||||
|
@ -377,12 +377,29 @@
|
|||
<span id="ldaptestloginstatus"></span>
|
||||
</div>
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
<p class="help-block">Enter a valid LDAP username and password to test whether your LDAP login is configured correctly.</p>
|
||||
<p class="help-block">{{ trans('admin/settings/general.ldap_login_test_help') }}</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- LDAP Forgotten password -->
|
||||
<div class="form-group {{ $errors->has('custom_forgot_pass_url') ? 'error' : '' }}">
|
||||
<div class="col-md-3">
|
||||
{{ Form::label('custom_forgot_pass_url', trans('admin/settings/general.custom_forgot_pass_url')) }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
@if (config('app.lock_passwords')===true)
|
||||
{{ Form::text('custom_forgot_pass_url', Input::old('custom_forgot_pass_url', $setting->custom_forgot_pass_url), array('class' => 'form-control', 'disabled'=>'disabled','placeholder' => 'https://my.ldapserver-forgotpass.com')) }}
|
||||
@else
|
||||
{{ Form::text('custom_forgot_pass_url', Input::old('custom_forgot_pass_url', $setting->custom_forgot_pass_url), array('class' => 'form-control','placeholder' => 'https://my.ldapserver-forgotpass.com')) }}
|
||||
@endif
|
||||
<p class="help-block">{{ trans('admin/settings/general.custom_forgot_pass_url_help') }}</p>
|
||||
{!! $errors->first('custom_forgot_pass_url', '<span class="alert-msg">:message</span>') !!}
|
||||
</div>
|
||||
</div><!-- LDAP Server -->
|
||||
|
||||
|
||||
</div>
|
||||
</div> <!--/.box-body-->
|
||||
<div class="box-footer">
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
<tr>
|
||||
<th data-sortable="true" data-field="id" data-visible="false">{{ trans('general.id') }}</th>
|
||||
<th data-sortable="true" data-field="name" data-formatter="statuslabelsAssetLinkFormatter">{{ trans('admin/statuslabels/table.name') }}</th>
|
||||
<th data-sortable="false" data-field="type" data-formatter="undeployableFormatter">{{ trans('admin/statuslabels/table.status_type') }}</th>
|
||||
<th data-sortable="false" data-field="type" data-formatter="statusLabelTypeFormatter">{{ trans('admin/statuslabels/table.status_type') }}</th>
|
||||
<th data-sortable="true" data-field="assets_count">{{ trans('general.assets') }}</th>
|
||||
<th data-sortable="false" data-field="color" data-formatter="colorSqFormatter">{{ trans('admin/statuslabels/table.color') }}</th>
|
||||
<th class="text-center" data-sortable="true" data-field="show_in_nav" data-formatter="trueFalseFormatter">{{ trans('admin/statuslabels/table.show_in_nav') }}</th>
|
||||
<th data-switchable="false" data-formatter="statuslabelsActionsFormatter" data-searchable="false" data-sortable="false" data-field="actions">{{ trans('table.actions') }}</th>
|
||||
|
@ -47,10 +48,28 @@
|
|||
<h4>{{ trans('admin/statuslabels/table.about') }}</h4>
|
||||
<p>{{ trans('admin/statuslabels/table.info') }}</p>
|
||||
|
||||
<p><i class="fa fa-circle text-green"></i> <strong>{{ trans('admin/statuslabels/table.deployable') }}</strong>: {!! trans('admin/statuslabels/message.help.deployable') !!}</p>
|
||||
<p><i class="fa fa-circle text-orange"></i> <strong>Pending</strong>: {{ trans('admin/statuslabels/message.help.pending') }}</p>
|
||||
<p><i class="fa fa-times text-red"></i> <strong>Undeployable</strong>: {{ trans('admin/statuslabels/message.help.undeployable') }}</p>
|
||||
<p><i class="fa fa-times text-red"></i> <strong>Archived</strong>: {{ trans('admin/statuslabels/message.help.archived') }}</p>
|
||||
<div class="box box-success">
|
||||
<div class="box-body">
|
||||
<p><i class="fa fa-circle text-green"></i> <strong>{{ trans('admin/statuslabels/table.deployable') }}</strong>: {!! trans('admin/statuslabels/message.help.deployable') !!}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box box-warning">
|
||||
<div class="box-body">
|
||||
<p><i class="fa fa-circle text-orange"></i> <strong>Pending</strong>: {{ trans('admin/statuslabels/message.help.pending') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box box-danger">
|
||||
<div class="box-body">
|
||||
<p><i class="fa fa-times text-red"></i> <strong>Undeployable</strong>: {{ trans('admin/statuslabels/message.help.undeployable') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box box-danger">
|
||||
<div class="box-body">
|
||||
<p><i class="fa fa-times text-red"></i> <strong>Archived</strong>: {{ trans('admin/statuslabels/message.help.archived') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -73,12 +92,30 @@
|
|||
}
|
||||
}
|
||||
|
||||
function undeployableFormatter(value, row) {
|
||||
if ((value) && (value!='deployable')) {
|
||||
return '<span class="text-danger">' + value + '</span> ';
|
||||
} else {
|
||||
return '<span class="text-success">' + value + '</span> ';
|
||||
function statusLabelTypeFormatter (row, value) {
|
||||
switch (value.type) {
|
||||
case 'deployed':
|
||||
text_color = 'blue';
|
||||
icon_style = 'fa-circle';
|
||||
break;
|
||||
case 'deployable':
|
||||
text_color = 'green';
|
||||
icon_style = 'fa-circle';
|
||||
break;
|
||||
case 'pending':
|
||||
text_color = 'orange';
|
||||
icon_style = 'fa-circle';
|
||||
break;
|
||||
default:
|
||||
text_color = 'red';
|
||||
icon_style = 'fa-times';
|
||||
}
|
||||
|
||||
var typename_lower = value.type;
|
||||
var typename = typename_lower.charAt(0).toUpperCase() + typename_lower.slice(1);
|
||||
return '<i class="fa ' + icon_style + ' text-' + text_color + '"></i> ' + typename;
|
||||
|
||||
|
||||
}
|
||||
</script>
|
||||
@stop
|
||||
|
|
|
@ -30,14 +30,16 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th data-sortable="true" data-field="id" data-visible="false">{{ trans('admin/suppliers/table.id') }}</th>
|
||||
<th data-formatter="imageFormatter" data-sortable="true" data-field="image" data-visible="false" data-searchable="false">Image</th>
|
||||
<th data-sortable="true" data-field="name" data-formatter="suppliersLinkFormatter">{{ trans('admin/suppliers/table.name') }}</th>
|
||||
<th data-sortable="true" data-field="address">{{ trans('admin/suppliers/table.address') }}</th>
|
||||
<th data-searchable="true" data-sortable="true" data-field="contact">{{ trans('admin/suppliers/table.contact') }}</th>
|
||||
<th data-searchable="true" data-sortable="true" data-field="email" data-formatter="emailFormatter">{{ trans('admin/suppliers/table.email') }}</th>
|
||||
<th data-searchable="true" data-sortable="true" data-field="phone">{{ trans('admin/suppliers/table.phone') }}</th>
|
||||
<th data-searchable="true" data-sortable="true" data-field="fax" data-visible="false">{{ trans('admin/suppliers/table.fax') }}</th>
|
||||
<th data-searchable="false" data-sortable="false" data-field="assets_count">{{ trans('admin/suppliers/table.assets') }}</th>
|
||||
<th data-searchable="false" data-sortable="false" data-field="licenses_count">{{ trans('admin/suppliers/table.licenses') }}</th>
|
||||
<th data-searchable="false" data-sortable="true" data-field="assets_count">{{ trans('admin/suppliers/table.assets') }}</th>
|
||||
<th data-searchable="false" data-sortable="true" data-field="accessories_count">{{ trans('general.accessories') }}</th>
|
||||
<th data-searchable="false" data-sortable="true" data-field="licenses_count">{{ trans('admin/suppliers/table.licenses') }}</th>
|
||||
<th data-switchable="false" data-formatter="suppliersActionsFormatter" data-searchable="false" data-sortable="false" data-field="actions">{{ trans('table.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
|
@ -137,6 +137,40 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="col-md-9">
|
||||
|
||||
<div class="box box-default">
|
||||
<div class="box-header with-border">
|
||||
<div class="box-heading">
|
||||
<h3 class="box-title">Accessories</h3>
|
||||
</div>
|
||||
</div><!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
<div class="table-responsive">
|
||||
|
||||
<table
|
||||
name="suppliersAccessories"
|
||||
id="table"
|
||||
class="snipe-table"
|
||||
data-url="{{ route('api.accessories.index', ['supplier_id' => $supplier->id]) }}"
|
||||
data-cookie="true"
|
||||
data-export-options='{"fileName": "testo"}'
|
||||
data-click-to-select="true"
|
||||
data-cookie-id-table="suppliersAccessories-{{ config('version.hash_version') }}">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-md-4" data-field="name" data-formatter="accessoriesLinkFormatter">Name</th>
|
||||
<th class="col-md-4" data-field="model_number">Model Number</th>
|
||||
<th class="col-md-4" data-field="purchase_cost" data-footer-formatter="sumFormatter">Purchase_cost</th>
|
||||
|
||||
<th class="col-md-4" data-field="actions" data-formatter="accessoriesActionsFormatter">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="box box-default">
|
||||
|
||||
@if ($supplier->id)
|
||||
|
@ -239,3 +273,8 @@
|
|||
</div> <!-- /.row-->
|
||||
|
||||
@stop
|
||||
@section('moar_scripts')
|
||||
@include ('partials.bootstrap-table', [
|
||||
'showFooter' => true,
|
||||
])
|
||||
@stop
|
||||
|
|
Loading…
Reference in a new issue