mirror of
https://github.com/snipe/snipe-it.git
synced 2024-11-09 23:24:06 -08:00
Merge branch 'develop' into snipeit_v7_laravel10
This commit is contained in:
commit
f64b0d3818
|
@ -2970,6 +2970,15 @@
|
|||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "mmanjos",
|
||||
"name": "mmanjos",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3483684?v=4",
|
||||
"profile": "https://github.com/mmanjos",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -159,6 +159,7 @@ LOG_CHANNEL=stderr
|
|||
LOG_MAX_DAYS=10
|
||||
APP_LOCKED=false
|
||||
APP_CIPHER=AES-256-CBC
|
||||
APP_FORCE_TLS=false
|
||||
GOOGLE_MAPS_API=
|
||||
LDAP_MEM_LIM=500M
|
||||
LDAP_TIME_LIM=600
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.svg)](https://crowdin.com/project/snipe-it) [![Docker Pulls](https://img.shields.io/docker/pulls/snipe/snipe-it.svg)](https://hub.docker.com/r/snipe/snipe-it/) [![Twitter Follow](https://img.shields.io/twitter/follow/snipeitapp.svg?style=social)](https://twitter.com/snipeitapp) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/553ce52037fc43ea99149785afcfe641)](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade)
|
||||
[![All Contributors](https://img.shields.io/badge/all_contributors-327-orange.svg?style=flat-square)](#contributors) [![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.gg/yZFtShAcKk) [![huntr](https://cdn.huntr.dev/huntr_security_badge_mono.svg)](https://huntr.dev)
|
||||
[![All Contributors](https://img.shields.io/badge/all_contributors-328-orange.svg?style=flat-square)](#contributors) [![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.gg/yZFtShAcKk) [![huntr](https://cdn.huntr.dev/huntr_security_badge_mono.svg)](https://huntr.dev)
|
||||
|
||||
## Snipe-IT - Open Source Asset Management System
|
||||
|
||||
|
@ -145,7 +145,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
|
|||
| [<img src="https://avatars.githubusercontent.com/u/28321?v=4" width="110px;"/><br /><sub>Chris Hartjes</sub>](http://www.littlehart.net/atthekeyboard)<br />[💻](https://github.com/snipe/snipe-it/commits?author=chartjes "Code") | [<img src="https://avatars.githubusercontent.com/u/2404584?v=4" width="110px;"/><br /><sub>geo-chen</sub>](https://github.com/geo-chen)<br />[💻](https://github.com/snipe/snipe-it/commits?author=geo-chen "Code") | [<img src="https://avatars.githubusercontent.com/u/6006620?v=4" width="110px;"/><br /><sub>Phan Nguyen</sub>](https://github.com/nh314)<br />[💻](https://github.com/snipe/snipe-it/commits?author=nh314 "Code") | [<img src="https://avatars.githubusercontent.com/u/115993812?v=4" width="110px;"/><br /><sub>Iisakki Jaakkola</sub>](https://github.com/StarlessNights)<br />[💻](https://github.com/snipe/snipe-it/commits?author=StarlessNights "Code") | [<img src="https://avatars.githubusercontent.com/u/22633385?v=4" width="110px;"/><br /><sub>Ikko Ashimine</sub>](https://bandism.net/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=eltociear "Code") | [<img src="https://avatars.githubusercontent.com/u/56871540?v=4" width="110px;"/><br /><sub>Lukas Fehling</sub>](https://github.com/lukasfehling)<br />[💻](https://github.com/snipe/snipe-it/commits?author=lukasfehling "Code") | [<img src="https://avatars.githubusercontent.com/u/1975990?v=4" width="110px;"/><br /><sub>Fernando Almeida</sub>](https://github.com/fernando-almeida)<br />[💻](https://github.com/snipe/snipe-it/commits?author=fernando-almeida "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/116301219?v=4" width="110px;"/><br /><sub>akemidx</sub>](https://github.com/akemidx)<br />[💻](https://github.com/snipe/snipe-it/commits?author=akemidx "Code") | [<img src="https://avatars.githubusercontent.com/u/144778?v=4" width="110px;"/><br /><sub>Oguz Bilgic</sub>](http://oguz.site)<br />[💻](https://github.com/snipe/snipe-it/commits?author=oguzbilgic "Code") | [<img src="https://avatars.githubusercontent.com/u/9262438?v=4" width="110px;"/><br /><sub>Scooter Crawford</sub>](https://github.com/scoo73r)<br />[💻](https://github.com/snipe/snipe-it/commits?author=scoo73r "Code") | [<img src="https://avatars.githubusercontent.com/u/5957345?v=4" width="110px;"/><br /><sub>subdriven</sub>](https://github.com/subdriven)<br />[💻](https://github.com/snipe/snipe-it/commits?author=subdriven "Code") | [<img src="https://avatars.githubusercontent.com/u/658865?v=4" width="110px;"/><br /><sub>Andrew Savinykh</sub>](https://github.com/AndrewSav)<br />[💻](https://github.com/snipe/snipe-it/commits?author=AndrewSav "Code") | [<img src="https://avatars.githubusercontent.com/u/1155067?v=4" width="110px;"/><br /><sub>Tadayuki Onishi</sub>](https://kenchan0130.github.io)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kenchan0130 "Code") | [<img src="https://avatars.githubusercontent.com/u/112496896?v=4" width="110px;"/><br /><sub>Florian</sub>](https://github.com/floschoepfer)<br />[💻](https://github.com/snipe/snipe-it/commits?author=floschoepfer "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/7305753?v=4" width="110px;"/><br /><sub>Spencer Long</sub>](http://spencerlong.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=spencerrlongg "Code") | [<img src="https://avatars.githubusercontent.com/u/1141514?v=4" width="110px;"/><br /><sub>Marcus Moore</sub>](https://github.com/marcusmoore)<br />[💻](https://github.com/snipe/snipe-it/commits?author=marcusmoore "Code") | [<img src="https://avatars.githubusercontent.com/u/570639?v=4" width="110px;"/><br /><sub>Martin Meredith</sub>](https://github.com/Mezzle)<br /> | [<img src="https://avatars.githubusercontent.com/u/5731963?v=4" width="110px;"/><br /><sub>dboth</sub>](http://dboth.de)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dboth "Code") | [<img src="https://avatars.githubusercontent.com/u/87536651?v=4" width="110px;"/><br /><sub>Zachary Fleck</sub>](https://github.com/zacharyfleck)<br />[💻](https://github.com/snipe/snipe-it/commits?author=zacharyfleck "Code") | [<img src="https://avatars.githubusercontent.com/u/74609912?v=4" width="110px;"/><br /><sub>VIKAAS-A</sub>](https://github.com/vikaas-cyper)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vikaas-cyper "Code") | [<img src="https://avatars.githubusercontent.com/u/88882041?v=4" width="110px;"/><br /><sub>Abdul Kareem</sub>](https://github.com/ak-piracha)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ak-piracha "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/111287779?v=4" width="110px;"/><br /><sub>NojoudAlshehri</sub>](https://github.com/NojoudAlshehri)<br />[💻](https://github.com/snipe/snipe-it/commits?author=NojoudAlshehri "Code") | [<img src="https://avatars.githubusercontent.com/u/54367449?v=4" width="110px;"/><br /><sub>Stefan Stidl</sub>](https://github.com/stefanstidlffg)<br />[💻](https://github.com/snipe/snipe-it/commits?author=stefanstidlffg "Code") | [<img src="https://avatars.githubusercontent.com/u/87803479?v=4" width="110px;"/><br /><sub>Quentin Aymard</sub>](https://github.com/qay21)<br />[💻](https://github.com/snipe/snipe-it/commits?author=qay21 "Code") | [<img src="https://avatars.githubusercontent.com/u/5396871?v=4" width="110px;"/><br /><sub>Grant Le Roux</sub>](https://github.com/cram42)<br />[💻](https://github.com/snipe/snipe-it/commits?author=cram42 "Code") | [<img src="https://avatars.githubusercontent.com/u/58479551?v=4" width="110px;"/><br /><sub>Bogdan</sub>](http://@singrity)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Singrity "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/111287779?v=4" width="110px;"/><br /><sub>NojoudAlshehri</sub>](https://github.com/NojoudAlshehri)<br />[💻](https://github.com/snipe/snipe-it/commits?author=NojoudAlshehri "Code") | [<img src="https://avatars.githubusercontent.com/u/54367449?v=4" width="110px;"/><br /><sub>Stefan Stidl</sub>](https://github.com/stefanstidlffg)<br />[💻](https://github.com/snipe/snipe-it/commits?author=stefanstidlffg "Code") | [<img src="https://avatars.githubusercontent.com/u/87803479?v=4" width="110px;"/><br /><sub>Quentin Aymard</sub>](https://github.com/qay21)<br />[💻](https://github.com/snipe/snipe-it/commits?author=qay21 "Code") | [<img src="https://avatars.githubusercontent.com/u/5396871?v=4" width="110px;"/><br /><sub>Grant Le Roux</sub>](https://github.com/cram42)<br />[💻](https://github.com/snipe/snipe-it/commits?author=cram42 "Code") | [<img src="https://avatars.githubusercontent.com/u/58479551?v=4" width="110px;"/><br /><sub>Bogdan</sub>](http://@singrity)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Singrity "Code") | [<img src="https://avatars.githubusercontent.com/u/3483684?v=4" width="110px;"/><br /><sub>mmanjos</sub>](https://github.com/mmanjos)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mmanjos "Code") |
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
|
|
@ -18,7 +18,7 @@ class LdapSync extends Command
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'snipeit:ldap-sync {--location=} {--location_id=} {--base_dn=} {--filter=} {--summary} {--json_summary}';
|
||||
protected $signature = 'snipeit:ldap-sync {--location=} {--location_id=*} {--base_dn=} {--filter=} {--summary} {--json_summary}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
|
@ -83,7 +83,15 @@ class LdapSync extends Command
|
|||
$summary = [];
|
||||
|
||||
try {
|
||||
if ($this->option('base_dn') != '') {
|
||||
if ( $this->option('location_id') != '') {
|
||||
|
||||
foreach($this->option('location_id') as $location_id){
|
||||
$location_ou= Location::where('id', '=', $location_id)->value('ldap_ou');
|
||||
$search_base = $location_ou;
|
||||
Log::debug('Importing users from specified location OU: \"'.$search_base.'\".');
|
||||
}
|
||||
}
|
||||
else if ($this->option('base_dn') != '') {
|
||||
$search_base = $this->option('base_dn');
|
||||
Log::debug('Importing users from specified base DN: \"'.$search_base.'\".');
|
||||
} else {
|
||||
|
@ -106,21 +114,21 @@ class LdapSync extends Command
|
|||
|
||||
/* Determine which location to assign users to by default. */
|
||||
$location = null; // TODO - this would be better called "$default_location", which is more explicit about its purpose
|
||||
if ($this->option('location') != '') {
|
||||
if ($location = Location::where('name', '=', $this->option('location'))->first()) {
|
||||
Log::debug('Location name ' . $this->option('location') . ' passed');
|
||||
Log::debug('Importing to ' . $location->name . ' (' . $location->id . ')');
|
||||
}
|
||||
|
||||
} elseif ($this->option('location_id') != '') {
|
||||
foreach($this->option('location_id') as $location_id) {
|
||||
if ($location = Location::where('id', '=', $location_id)->first()) {
|
||||
Log::debug('Location ID ' . $location_id . ' passed');
|
||||
Log::debug('Importing to ' . $location->name . ' (' . $location->id . ')');
|
||||
}
|
||||
|
||||
if ($this->option('location') != '') {
|
||||
if ($location = Location::where('name', '=', $this->option('location'))->first()) {
|
||||
Log::debug('Location name '.$this->option('location').' passed');
|
||||
Log::debug('Importing to '.$location->name.' ('.$location->id.')');
|
||||
}
|
||||
|
||||
} elseif ($this->option('location_id') != '') {
|
||||
if ($location = Location::where('id', '=', $this->option('location_id'))->first()) {
|
||||
Log::debug('Location ID '.$this->option('location_id').' passed');
|
||||
Log::debug('Importing to '.$location->name.' ('.$location->id.')');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! isset($location)) {
|
||||
Log::debug('That location is invalid or a location was not provided, so no location will be assigned by default.');
|
||||
}
|
||||
|
|
|
@ -150,6 +150,11 @@ class Handler extends ExceptionHandler
|
|||
return redirect()->guest('login');
|
||||
}
|
||||
|
||||
protected function invalidJson($request, ValidationException $exception)
|
||||
{
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $exception->errors()), 200);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A list of the inputs that are never flashed for validation exceptions.
|
||||
|
|
|
@ -73,10 +73,14 @@ class Helper
|
|||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.3]
|
||||
* @return array
|
||||
* @return string
|
||||
*/
|
||||
public static function defaultChartColors($index = 0)
|
||||
public static function defaultChartColors(int $index = 0)
|
||||
{
|
||||
if ($index < 0) {
|
||||
$index = 0;
|
||||
}
|
||||
|
||||
$colors = [
|
||||
'#008941',
|
||||
'#FF4A46',
|
||||
|
@ -349,7 +353,19 @@ class Helper
|
|||
$total_colors = count($colors);
|
||||
|
||||
if ($index >= $total_colors) {
|
||||
$index = $index - $total_colors;
|
||||
|
||||
\Log::error('Status label count is '.$index.' and exceeds the allowed count of 266.');
|
||||
//patch fix for array key overflow (color count starts at 1, array starts at 0)
|
||||
$index = $index - $total_colors - 1;
|
||||
|
||||
//constraints to keep result in 0-265 range. This should never be needed, but if something happens
|
||||
//to create this many status labels and it DOES happen, this will keep it from failing at least.
|
||||
if($index < 0) {
|
||||
$index = 0;
|
||||
}
|
||||
elseif($index >($total_colors - 1)) {
|
||||
$index = $total_colors - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return $colors[$index];
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Events\CheckoutableCheckedIn;
|
||||
use App\Http\Requests\StoreAssetRequest;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
@ -33,6 +34,7 @@ use TCPDF;
|
|||
use Validator;
|
||||
use Route;
|
||||
|
||||
|
||||
/**
|
||||
* This class controls all actions related to assets for
|
||||
* the Snipe-IT Asset Management application.
|
||||
|
@ -48,7 +50,7 @@ class AssetsController extends Controller
|
|||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @since [v4.0]
|
||||
* @return JsonResponse
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function index(Request $request, $audit = null)
|
||||
{
|
||||
|
@ -295,7 +297,7 @@ class AssetsController extends Controller
|
|||
}
|
||||
|
||||
if ($request->filled('order_number')) {
|
||||
$assets->where('assets.order_number', '=', $request->get('order_number'));
|
||||
$assets->where('assets.order_number', '=', strval($request->get('order_number')));
|
||||
}
|
||||
|
||||
// This is kinda gross, but we need to do this because the Bootstrap Tables
|
||||
|
@ -443,7 +445,7 @@ class AssetsController extends Controller
|
|||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @since [v4.0]
|
||||
* @return JsonResponse
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function show(Request $request, $id)
|
||||
{
|
||||
|
@ -474,7 +476,7 @@ class AssetsController extends Controller
|
|||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0.16]
|
||||
* @see \App\Http\Transformers\SelectlistTransformer
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function selectlist(Request $request)
|
||||
{
|
||||
|
@ -530,12 +532,10 @@ class AssetsController extends Controller
|
|||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param \App\Http\Requests\ImageUploadRequest $request
|
||||
* @since [v4.0]
|
||||
* @return JsonResponse
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function store(ImageUploadRequest $request)
|
||||
public function store(StoreAssetRequest $request)
|
||||
{
|
||||
$this->authorize('create', Asset::class);
|
||||
|
||||
$asset = new Asset();
|
||||
$asset->model()->associate(AssetModel::find((int) $request->get('model_id')));
|
||||
|
||||
|
@ -639,7 +639,7 @@ class AssetsController extends Controller
|
|||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param \App\Http\Requests\ImageUploadRequest $request
|
||||
* @since [v4.0]
|
||||
* @return JsonResponse
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $id)
|
||||
{
|
||||
|
@ -666,10 +666,11 @@ class AssetsController extends Controller
|
|||
$request->offsetSet('image', $request->offsetGet('image_source'));
|
||||
}
|
||||
|
||||
$asset = $request->handleImages($asset);
|
||||
$asset = $request->handleImages($asset);
|
||||
$model = AssetModel::find($asset->model_id);
|
||||
|
||||
// Update custom fields
|
||||
if (($model = AssetModel::find($asset->model_id)) && (isset($model->fieldset))) {
|
||||
if (($model) && (isset($model->fieldset))) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
if ($request->has($field->db_column)) {
|
||||
if ($field->field_encrypted == '1') {
|
||||
|
@ -720,7 +721,7 @@ class AssetsController extends Controller
|
|||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @since [v4.0]
|
||||
* @return JsonResponse
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
|
@ -749,7 +750,7 @@ class AssetsController extends Controller
|
|||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @since [v5.1.18]
|
||||
* @return JsonResponse
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function restore(Request $request, $assetId = null)
|
||||
{
|
||||
|
@ -789,7 +790,7 @@ class AssetsController extends Controller
|
|||
* @author [N. Butler]
|
||||
* @param string $tag
|
||||
* @since [v6.0.5]
|
||||
* @return JsonResponse
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function checkoutByTag(AssetCheckoutRequest $request, $tag)
|
||||
{
|
||||
|
@ -805,7 +806,7 @@ class AssetsController extends Controller
|
|||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @since [v4.0]
|
||||
* @return JsonResponse
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function checkout(AssetCheckoutRequest $request, $asset_id)
|
||||
{
|
||||
|
@ -889,7 +890,7 @@ class AssetsController extends Controller
|
|||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @since [v4.0]
|
||||
* @return JsonResponse
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function checkin(Request $request, $asset_id)
|
||||
{
|
||||
|
@ -945,7 +946,7 @@ class AssetsController extends Controller
|
|||
*
|
||||
* @author [A. Janes] [<ajanes@adagiohealth.org>]
|
||||
* @since [v6.0]
|
||||
* @return JsonResponse
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function checkinByTag(Request $request, $tag = null)
|
||||
{
|
||||
|
@ -971,7 +972,7 @@ class AssetsController extends Controller
|
|||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $id
|
||||
* @since [v4.0]
|
||||
* @return JsonResponse
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function audit(Request $request)
|
||||
|
||||
|
@ -1032,24 +1033,54 @@ class AssetsController extends Controller
|
|||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
* @return JsonResponse
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function requestable(Request $request)
|
||||
{
|
||||
$this->authorize('viewRequestable', Asset::class);
|
||||
|
||||
$allowed_columns = [
|
||||
'name',
|
||||
'asset_tag',
|
||||
'serial',
|
||||
'model_number',
|
||||
'image',
|
||||
'purchase_cost',
|
||||
'expected_checkin',
|
||||
];
|
||||
|
||||
$all_custom_fields = CustomField::all(); //used as a 'cache' of custom fields throughout this page load
|
||||
|
||||
foreach ($all_custom_fields as $field) {
|
||||
$allowed_columns[] = $field->db_column_name();
|
||||
}
|
||||
|
||||
$assets = Asset::select('assets.*')
|
||||
->with('location', 'assetstatus', 'assetlog', 'company', 'defaultLoc','assignedTo',
|
||||
'model.category', 'model.manufacturer', 'model.fieldset', 'supplier')
|
||||
->with('location', 'assetstatus', 'assetlog', 'company','assignedTo',
|
||||
'model.category', 'model.manufacturer', 'model.fieldset', 'supplier', 'requests')
|
||||
->requestableAssets();
|
||||
|
||||
$offset = request('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$assets->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
// Search custom fields by column name
|
||||
foreach ($all_custom_fields as $field) {
|
||||
if ($request->filled($field->db_column_name())) {
|
||||
$assets->where($field->db_column_name(), '=', $request->input($field->db_column_name()));
|
||||
}
|
||||
}
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort_override = str_replace('custom_fields.', '', $request->input('sort'));
|
||||
|
||||
// This handles all the pivot sorting (versus the assets.* fields
|
||||
// in the allowed_columns array)
|
||||
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'assets.created_at';
|
||||
|
||||
switch ($request->input('sort')) {
|
||||
case 'model':
|
||||
$assets->OrderModels($order);
|
||||
|
@ -1057,17 +1088,19 @@ class AssetsController extends Controller
|
|||
case 'model_number':
|
||||
$assets->OrderModelNumber($order);
|
||||
break;
|
||||
case 'category':
|
||||
$assets->OrderCategory($order);
|
||||
break;
|
||||
case 'manufacturer':
|
||||
$assets->OrderManufacturer($order);
|
||||
case 'location':
|
||||
$assets->OrderLocation($order);
|
||||
break;
|
||||
default:
|
||||
$assets->orderBy('assets.created_at', $order);
|
||||
$assets->orderBy($column_sort, $order);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $assets->count()) ? $assets->count() : app('api_offset_value');
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$total = $assets->count();
|
||||
$assets = $assets->skip($offset)->take($limit)->get();
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ use Illuminate\Http\Request;
|
|||
use Laravel\Passport\TokenRepository;
|
||||
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use App\Models\CustomField;
|
||||
use DB;
|
||||
|
||||
class ProfileController extends Controller
|
||||
|
@ -48,14 +49,23 @@ class ProfileController extends Controller
|
|||
{
|
||||
$checkoutRequests = CheckoutRequest::where('user_id', '=', Auth::user()->id)->get();
|
||||
|
||||
$results = [];
|
||||
$results = array();
|
||||
$show_field = array();
|
||||
$showable_fields = array();
|
||||
$results['total'] = $checkoutRequests->count();
|
||||
|
||||
$all_custom_fields = CustomField::all(); //used as a 'cache' of custom fields throughout this page load
|
||||
foreach ($all_custom_fields as $field) {
|
||||
if (($field->field_encrypted=='0') && ($field->show_in_requestable_list=='1')) {
|
||||
$showable_fields[] = $field->db_column_name();
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($checkoutRequests as $checkoutRequest) {
|
||||
|
||||
// Make sure the asset and request still exist
|
||||
if ($checkoutRequest && $checkoutRequest->itemRequested()) {
|
||||
$results['rows'][] = [
|
||||
$assets = [
|
||||
'image' => e($checkoutRequest->itemRequested()->present()->getImageUrl()),
|
||||
'name' => e($checkoutRequest->itemRequested()->present()->name()),
|
||||
'type' => e($checkoutRequest->itemType()),
|
||||
|
@ -64,7 +74,16 @@ class ProfileController extends Controller
|
|||
'expected_checkin' => Helper::getFormattedDateObject($checkoutRequest->itemRequested()->expected_checkin, 'datetime'),
|
||||
'request_date' => Helper::getFormattedDateObject($checkoutRequest->created_at, 'datetime'),
|
||||
];
|
||||
|
||||
foreach ($showable_fields as $showable_field_name) {
|
||||
$show_field['custom_fields.'.$showable_field_name] = $checkoutRequest->itemRequested()->{$showable_field_name};
|
||||
}
|
||||
|
||||
// Merge the plain asset data and the custom fields data
|
||||
$results['rows'][] = array_merge($assets, $show_field);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return $results;
|
||||
|
|
|
@ -179,9 +179,14 @@ class AssetModelsController extends Controller
|
|||
|
||||
if ($model->save()) {
|
||||
if ($model->wasChanged('eol')) {
|
||||
$newEol = $model->eol;
|
||||
$model->assets()->whereNotNull('purchase_date')->where('eol_explicit', false)
|
||||
->update(['asset_eol_date' => DB::raw('DATE_ADD(purchase_date, INTERVAL ' . $newEol . ' MONTH)')]);
|
||||
if ($model->eol > 0) {
|
||||
$newEol = $model->eol;
|
||||
$model->assets()->whereNotNull('purchase_date')->where('eol_explicit', false)
|
||||
->update(['asset_eol_date' => DB::raw('DATE_ADD(purchase_date, INTERVAL ' . $newEol . ' MONTH)')]);
|
||||
} elseif ($model->eol == 0) {
|
||||
$model->assets()->whereNotNull('purchase_date')->where('eol_explicit', false)
|
||||
->update(['asset_eol_date' => DB::raw('null')]);
|
||||
}
|
||||
}
|
||||
return redirect()->route('models.index')->with('success', trans('admin/models/message.update.success'));
|
||||
}
|
||||
|
|
|
@ -137,7 +137,7 @@ class AssetsController extends Controller
|
|||
$asset->warranty_months = request('warranty_months', null);
|
||||
$asset->purchase_cost = request('purchase_cost');
|
||||
$asset->purchase_date = request('purchase_date', null);
|
||||
$asset->asset_eol_date = request('asset_eol_date', $asset->present()->eol_date());
|
||||
$asset->asset_eol_date = request('asset_eol_date', null);
|
||||
$asset->assigned_to = request('assigned_to', null);
|
||||
$asset->supplier_id = request('supplier_id', null);
|
||||
$asset->requestable = request('requestable', 0);
|
||||
|
@ -204,12 +204,8 @@ class AssetsController extends Controller
|
|||
}
|
||||
|
||||
if ($success) {
|
||||
// Redirect to the asset listing page
|
||||
$minutes = 518400;
|
||||
// dd( $_POST['options']);
|
||||
// Cookie::queue(Cookie::make('optional_info', json_decode($_POST['options']), $minutes));
|
||||
return redirect()->route('hardware.index')
|
||||
->with('success', trans('admin/hardware/message.create.success'));
|
||||
->with('success-unescaped', trans('admin/hardware/message.create.success_linked', ['link' => route('hardware.show', $asset->id), 'id', 'tag' => $asset->asset_tag]));
|
||||
|
||||
|
||||
}
|
||||
|
@ -309,14 +305,15 @@ class AssetsController extends Controller
|
|||
$asset->warranty_months = $request->input('warranty_months', null);
|
||||
$asset->purchase_cost = $request->input('purchase_cost', null);
|
||||
$asset->purchase_date = $request->input('purchase_date', null);
|
||||
if ($request->filled('purchase_date') && !$request->filled('asset_eol_date') && $asset->model->eol) {
|
||||
if ($request->filled('purchase_date') && !$request->filled('asset_eol_date') && ($asset->model->eol > 0)) {
|
||||
$asset->purchase_date = $request->input('purchase_date', null);
|
||||
$asset->asset_eol_date = Carbon::parse($request->input('purchase_date'))->addMonths($asset->model->eol)->format('Y-m-d');
|
||||
$asset->eol_explicit = false;
|
||||
} elseif ($request->filled('asset_eol_date')) {
|
||||
$asset->asset_eol_date = $request->input('asset_eol_date', null);
|
||||
$months = Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date);
|
||||
if($asset->model->eol) {
|
||||
if($months != $asset->model->eol) {
|
||||
if($months != $asset->model->eol > 0) {
|
||||
$asset->eol_explicit = true;
|
||||
} else {
|
||||
$asset->eol_explicit = false;
|
||||
|
@ -324,6 +321,9 @@ class AssetsController extends Controller
|
|||
} else {
|
||||
$asset->eol_explicit = true;
|
||||
}
|
||||
} elseif (!$request->filled('asset_eol_date') && (($asset->model->eol) == 0)) {
|
||||
$asset->asset_eol_date = null;
|
||||
$asset->eol_explicit = false;
|
||||
}
|
||||
$asset->supplier_id = $request->input('supplier_id', null);
|
||||
$asset->expected_checkin = $request->input('expected_checkin', null);
|
||||
|
|
|
@ -112,7 +112,8 @@ class BulkAssetsController extends Controller
|
|||
public function update(Request $request)
|
||||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
$error_bag = [];
|
||||
$has_errors = 0;
|
||||
$error_array = array();
|
||||
|
||||
// Get the back url from the session and then destroy the session
|
||||
$bulk_back_url = route('hardware.index');
|
||||
|
@ -120,10 +121,9 @@ class BulkAssetsController extends Controller
|
|||
$bulk_back_url = $request->session()->pull('bulk_back_url');
|
||||
}
|
||||
|
||||
|
||||
$custom_field_columns = CustomField::all()->pluck('db_column')->toArray();
|
||||
$custom_field_columns = CustomField::all()->pluck('db_column')->toArray();
|
||||
|
||||
if(Session::exists('ids')) {
|
||||
if (Session::exists('ids')) {
|
||||
$assets = Session::get('ids');
|
||||
} elseif (! $request->filled('ids') || count($request->input('ids')) <= 0) {
|
||||
return redirect($bulk_back_url)->with('error', trans('admin/hardware/message.update.no_assets_selected'));
|
||||
|
@ -160,7 +160,6 @@ class BulkAssetsController extends Controller
|
|||
|
||||
$this->conditionallyAddItem('purchase_date')
|
||||
->conditionallyAddItem('expected_checkin')
|
||||
->conditionallyAddItem('model_id')
|
||||
->conditionallyAddItem('order_number')
|
||||
->conditionallyAddItem('requestable')
|
||||
->conditionallyAddItem('status_id')
|
||||
|
@ -187,6 +186,7 @@ class BulkAssetsController extends Controller
|
|||
$this->update_array['purchase_cost'] = $request->input('purchase_cost');
|
||||
}
|
||||
|
||||
|
||||
if ($request->filled('company_id')) {
|
||||
$this->update_array['company_id'] = $request->input('company_id');
|
||||
if ($request->input('company_id') == 'clear') {
|
||||
|
@ -195,68 +195,108 @@ class BulkAssetsController extends Controller
|
|||
}
|
||||
|
||||
if ($request->filled('rtd_location_id')) {
|
||||
$this->update_array['rtd_location_id'] = $request->input('rtd_location_id');
|
||||
if (($request->filled('update_real_loc')) && (($request->input('update_real_loc')) == '0')) {
|
||||
$this->update_array['rtd_location_id'] = $request->input('rtd_location_id');
|
||||
}
|
||||
if (($request->filled('update_real_loc')) && (($request->input('update_real_loc')) == '1')) {
|
||||
$this->update_array['location_id'] = $request->input('rtd_location_id');
|
||||
$this->update_array['rtd_location_id'] = $request->input('rtd_location_id');
|
||||
}
|
||||
if (($request->filled('update_real_loc')) && (($request->input('update_real_loc')) == '2')) {
|
||||
$this->update_array['location_id'] = $request->input('rtd_location_id');
|
||||
}
|
||||
}
|
||||
|
||||
$changed = [];
|
||||
$assetCollection = Asset::where('id' ,$assetId)->get();
|
||||
$asset = Asset::find($assetId);
|
||||
|
||||
foreach ($this->update_array as $key => $value) {
|
||||
if ($this->update_array[$key] != $assetCollection->toArray()[0][$key]) {
|
||||
$changed[$key]['old'] = $assetCollection->toArray()[0][$key];
|
||||
if ($this->update_array[$key] != $asset->{$key}) {
|
||||
$changed[$key]['old'] = $asset->{$key};
|
||||
$changed[$key]['new'] = $this->update_array[$key];
|
||||
}
|
||||
}
|
||||
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = Asset::class;
|
||||
$logAction->item_id = $assetId;
|
||||
$logAction->created_at = date("Y-m-d H:i:s");
|
||||
$logAction->user_id = Auth::id();
|
||||
$logAction->log_meta = json_encode($changed);
|
||||
$logAction->logaction('update');
|
||||
|
||||
if($custom_fields_present) {
|
||||
$asset = Asset::find($assetId);
|
||||
$assetCustomFields = $asset->model()->first()->fieldset;
|
||||
if($assetCustomFields && $assetCustomFields->fields) {
|
||||
foreach ($assetCustomFields->fields as $field) {
|
||||
if (array_key_exists($field->db_column, $this->update_array)) {
|
||||
$asset->{$field->db_column} = $this->update_array[$field->db_column];
|
||||
$saved = $asset->save();
|
||||
if(!$saved) {
|
||||
$error_bag[] = $asset->getErrors();
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
$array = $this->update_array;
|
||||
array_except($array, $field->db_column);
|
||||
$asset->save($array);
|
||||
}
|
||||
if (!$asset->save()) {
|
||||
$error_bag[] = $asset->getErrors();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Asset::find($assetId)->update($this->update_array);
|
||||
}
|
||||
}
|
||||
if(!empty($error_bag)) {
|
||||
$errors = [];
|
||||
//find the customfield name from the name of the messagebag items
|
||||
foreach ($error_bag as $key => $bag) {
|
||||
foreach($bag->keys() as $key => $value) {
|
||||
CustomField::where('db_column', $value)->get()->map(function($item) use (&$errors) {
|
||||
$errors[] = $item->name;
|
||||
});
|
||||
if ($custom_fields_present) {
|
||||
|
||||
$model = $asset->model()->first();
|
||||
|
||||
// Use the rules of the new model fieldsets if the model changed
|
||||
if ($request->filled('model_id')) {
|
||||
$this->update_array['model_id'] = $request->input('model_id');
|
||||
$model = \App\Models\AssetModel::find($request->input('model_id'));
|
||||
}
|
||||
}
|
||||
return redirect($bulk_back_url)->with('bulk_errors', array_unique($errors));
|
||||
}
|
||||
|
||||
|
||||
// Make sure this model is valid
|
||||
$assetCustomFields = ($model) ? $model->fieldset : null;
|
||||
|
||||
if ($assetCustomFields && $assetCustomFields->fields) {
|
||||
|
||||
foreach ($assetCustomFields->fields as $field) {
|
||||
|
||||
if ((array_key_exists($field->db_column, $this->update_array)) && ($field->field_encrypted=='1')) {
|
||||
$decrypted_old = Helper::gracefulDecrypt($field, $asset->{$field->db_column});
|
||||
|
||||
/*
|
||||
* Check if the decrypted existing value is different from one we just submitted
|
||||
* and if not, pull it out of the object since it shouldn't really be updating at all.
|
||||
* If we don't do this, it will try to re-encrypt it, and the same value encrypted two
|
||||
* different times will have different values, so it will *look* like it was updated
|
||||
* but it wasn't.
|
||||
*/
|
||||
if ($decrypted_old != $this->update_array[$field->db_column]) {
|
||||
$asset->{$field->db_column} = \Crypt::encrypt($this->update_array[$field->db_column]);
|
||||
} else {
|
||||
/*
|
||||
* Remove the encrypted custom field from the update_array, since nothing changed
|
||||
*/
|
||||
unset($this->update_array[$field->db_column]);
|
||||
unset($asset->{$field->db_column});
|
||||
}
|
||||
|
||||
/*
|
||||
* These custom fields aren't encrypted, just carry on as usual
|
||||
*/
|
||||
} else {
|
||||
|
||||
|
||||
if ((array_key_exists($field->db_column, $this->update_array)) && ($asset->{$field->db_column} != $this->update_array[$field->db_column])) {
|
||||
|
||||
// Check if this is an array, and if so, flatten it
|
||||
if (is_array($this->update_array[$field->db_column])) {
|
||||
$asset->{$field->db_column} = implode(', ', $this->update_array[$field->db_column]);
|
||||
} else {
|
||||
$asset->{$field->db_column} = $this->update_array[$field->db_column];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // endforeach
|
||||
} // end custom field check
|
||||
} // end custom fields handler
|
||||
|
||||
|
||||
|
||||
// Check if it passes validation, and then try to save
|
||||
if (!$asset->update($this->update_array)) {
|
||||
|
||||
// Build the error array
|
||||
foreach ($asset->getErrors()->toArray() as $key => $message) {
|
||||
for ($x = 0; $x < count($message); $x++) {
|
||||
$error_array[$key][] = trans('general.asset') . ' ' . $asset->id . ': ' . $message[$x];
|
||||
$has_errors++;
|
||||
}
|
||||
}
|
||||
|
||||
} // end if saved
|
||||
|
||||
} // end asset foreach
|
||||
|
||||
if ($has_errors > 0) {
|
||||
return redirect($bulk_back_url)->with('bulk_asset_errors', $error_array);
|
||||
}
|
||||
|
||||
return redirect($bulk_back_url)->with('success', trans('admin/hardware/message.update.success'));
|
||||
}
|
||||
// no values given, nothing to update
|
||||
|
|
|
@ -96,8 +96,8 @@ class ComponentCheckinController extends Controller
|
|||
$asset = Asset::find($component_assets->asset_id);
|
||||
|
||||
event(new CheckoutableCheckedIn($component, $asset, Auth::user(), $request->input('note'), Carbon::now()));
|
||||
if($backto == 'asset'){
|
||||
return redirect()->route('hardware.view', $asset->id)->with('success',
|
||||
if ($backto == 'asset'){
|
||||
return redirect()->route('hardware.show', $asset->id)->with('success',
|
||||
trans('admin/components/message.checkin.success'));
|
||||
}
|
||||
|
||||
|
|
|
@ -110,6 +110,7 @@ class CustomFieldsController extends Controller
|
|||
"display_in_user_view" => $display_in_user_view,
|
||||
"auto_add_to_fieldsets" => $request->get("auto_add_to_fieldsets", 0),
|
||||
"show_in_listview" => $request->get("show_in_listview", 0),
|
||||
"show_in_requestable_list" => $request->get("show_in_requestable_list", 0),
|
||||
"user_id" => Auth::id()
|
||||
]);
|
||||
|
||||
|
@ -267,6 +268,7 @@ class CustomFieldsController extends Controller
|
|||
$field->display_in_user_view = $display_in_user_view;
|
||||
$field->auto_add_to_fieldsets = $request->get("auto_add_to_fieldsets", 0);
|
||||
$field->show_in_listview = $request->get("show_in_listview", 0);
|
||||
$field->show_in_requestable_list = $request->get("show_in_requestable_list", 0);
|
||||
|
||||
if ($request->get('format') == 'CUSTOM REGEX') {
|
||||
$field->format = e($request->get('custom_format'));
|
||||
|
|
|
@ -7,8 +7,10 @@ use App\Models\AssetModel;
|
|||
use App\Models\Category;
|
||||
use App\Models\Company;
|
||||
use App\Models\Labels\Label;
|
||||
use App\Models\Location;
|
||||
use App\Models\Manufacturer;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Supplier;
|
||||
use App\Models\User;
|
||||
use App\View\Label as LabelView;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
@ -33,18 +35,20 @@ class LabelsController extends Controller
|
|||
$exampleAsset->name = 'JEN-867-5309';
|
||||
$exampleAsset->asset_tag = '100001';
|
||||
$exampleAsset->serial = 'SN9876543210';
|
||||
$exampleAsset->asset_eol_date = '2025-01-01';
|
||||
$exampleAsset->order_number = '12345';
|
||||
$exampleAsset->purchase_date = '2023-01-01';
|
||||
$exampleAsset->status_id = 1;
|
||||
|
||||
$exampleAsset->company = new Company();
|
||||
$exampleAsset->company->id = 999999;
|
||||
$exampleAsset->company->name = 'Test Company Limited';
|
||||
$exampleAsset->company->image = 'company-image-test.png';
|
||||
$exampleAsset->company = new Company([
|
||||
'name' => 'Test Company Limited',
|
||||
'phone' => '1-555-555-5555',
|
||||
'email' => 'company@example.com',
|
||||
]);
|
||||
|
||||
$exampleAsset->assignedto = new User();
|
||||
$exampleAsset->assignedto->id = 999999;
|
||||
$exampleAsset->assignedto->first_name = 'Test';
|
||||
$exampleAsset->assignedto->last_name = 'Person';
|
||||
$exampleAsset->assignedto->username = 'Test.Person';
|
||||
$exampleAsset->assignedto->employee_num = '0123456789';
|
||||
$exampleAsset->setRelation('assignedTo', new User(['first_name' => 'Luke', 'last_name' => 'Skywalker']));
|
||||
$exampleAsset->defaultLoc = new Location(['name' => 'Building 1', 'phone' => '1-555-555-5555']);
|
||||
$exampleAsset->location = new Location(['name' => 'Building 2', 'phone' => '1-555-555-5555']);
|
||||
|
||||
$exampleAsset->model = new AssetModel();
|
||||
$exampleAsset->model->id = 999999;
|
||||
|
@ -53,6 +57,10 @@ class LabelsController extends Controller
|
|||
$exampleAsset->model->manufacturer = new Manufacturer();
|
||||
$exampleAsset->model->manufacturer->id = 999999;
|
||||
$exampleAsset->model->manufacturer->name = 'Test Manufacturing Inc.';
|
||||
$exampleAsset->model->manufacturer->support_email = 'support@test.com';
|
||||
$exampleAsset->model->manufacturer->support_phone = '1-555-555-5555';
|
||||
$exampleAsset->model->manufacturer->support_url = 'https://example.com';
|
||||
$exampleAsset->supplier = new Supplier(['name' => 'Test Company Limited']);
|
||||
$exampleAsset->model->category = new Category();
|
||||
$exampleAsset->model->category->id = 999999;
|
||||
$exampleAsset->model->category->name = 'Test Category';
|
||||
|
|
|
@ -101,7 +101,7 @@ class LicenseCheckinController extends Controller
|
|||
|
||||
// Was the asset updated?
|
||||
if ($licenseSeat->save()) {
|
||||
event(new CheckoutableCheckedIn($licenseSeat, $return_to, Auth::user(), $request->input('note')));
|
||||
event(new CheckoutableCheckedIn($licenseSeat, $return_to, Auth::user(), $request->input('notes')));
|
||||
|
||||
if ($backTo == 'user') {
|
||||
return redirect()->route('users.show', $return_to->id)->with('success', trans('admin/licenses/message.checkin.success'));
|
||||
|
|
|
@ -105,7 +105,7 @@ class LicenseCheckoutController extends Controller
|
|||
$licenseSeat->assigned_to = $target->assigned_to;
|
||||
}
|
||||
if ($licenseSeat->save()) {
|
||||
event(new CheckoutableCheckedOut($licenseSeat, $target, Auth::user(), request('note')));
|
||||
event(new CheckoutableCheckedOut($licenseSeat, $target, Auth::user(), request('notes')));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ class LicenseCheckoutController extends Controller
|
|||
$licenseSeat->assigned_to = request('assigned_to');
|
||||
|
||||
if ($licenseSeat->save()) {
|
||||
event(new CheckoutableCheckedOut($licenseSeat, $target, Auth::user(), request('note')));
|
||||
event(new CheckoutableCheckedOut($licenseSeat, $target, Auth::user(), request('notes')));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ use Input;
|
|||
use League\Csv\Reader;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use League\Csv\EscapeFormula;
|
||||
use App\Http\Requests\CustomAssetReportRequest;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -246,6 +247,9 @@ class ReportsController extends Controller
|
|||
trans('general.action'),
|
||||
trans('general.type'),
|
||||
trans('general.item'),
|
||||
trans('general.license_serial'),
|
||||
trans('general.model_name'),
|
||||
trans('general.model_no'),
|
||||
'To',
|
||||
trans('general.notes'),
|
||||
'Changed',
|
||||
|
@ -288,6 +292,9 @@ class ReportsController extends Controller
|
|||
$actionlog->present()->actionType(),
|
||||
e($actionlog->itemType()),
|
||||
($actionlog->itemType() == 'user') ? $actionlog->filename : $item_name,
|
||||
($actionlog->item->serial) ? $actionlog->item->serial : null,
|
||||
($actionlog->item->model) ? htmlspecialchars($actionlog->item->model->name, ENT_NOQUOTES) : null,
|
||||
($actionlog->item->model) ? $actionlog->item->model->model_number : null,
|
||||
$target_name,
|
||||
($actionlog->note) ? e($actionlog->note) : '',
|
||||
$actionlog->log_meta,
|
||||
|
@ -403,11 +410,12 @@ class ReportsController extends Controller
|
|||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function postCustom(Request $request)
|
||||
public function postCustom(CustomAssetReportRequest $request)
|
||||
{
|
||||
ini_set('max_execution_time', env('REPORT_TIME_LIMIT', 12000)); //12000 seconds = 200 minutes
|
||||
$this->authorize('reports.view');
|
||||
|
||||
|
||||
\Debugbar::disable();
|
||||
$customfields = CustomField::get();
|
||||
$response = new StreamedResponse(function () use ($customfields, $request) {
|
||||
|
@ -526,6 +534,30 @@ class ReportsController extends Controller
|
|||
$header[] = trans('admin/users/table.title');
|
||||
}
|
||||
|
||||
if ($request->filled('phone')) {
|
||||
$header[] = trans('admin/users/table.phone');
|
||||
}
|
||||
|
||||
if ($request->filled('user_address')) {
|
||||
$header[] = trans('admin/reports/general.custom_export.user_address');
|
||||
}
|
||||
|
||||
if ($request->filled('user_city')) {
|
||||
$header[] = trans('admin/reports/general.custom_export.user_city');
|
||||
}
|
||||
|
||||
if ($request->filled('user_state')) {
|
||||
$header[] = trans('admin/reports/general.custom_export.user_state');
|
||||
}
|
||||
|
||||
if ($request->filled('user_country')) {
|
||||
$header[] = trans('admin/reports/general.custom_export.user_country');
|
||||
}
|
||||
|
||||
if ($request->filled('user_zip')) {
|
||||
$header[] = trans('admin/reports/general.custom_export.user_zip');
|
||||
}
|
||||
|
||||
if ($request->filled('status')) {
|
||||
$header[] = trans('general.status');
|
||||
}
|
||||
|
@ -645,7 +677,7 @@ class ReportsController extends Controller
|
|||
if (($request->filled('created_start')) && ($request->filled('created_end'))) {
|
||||
$created_start = \Carbon::parse($request->input('created_start'))->startOfDay();
|
||||
$created_end = \Carbon::parse($request->input('created_end'))->endOfDay();
|
||||
|
||||
|
||||
$assets->whereBetween('assets.created_at', [$created_start, $created_end]);
|
||||
}
|
||||
if (($request->filled('checkout_date_start')) && ($request->filled('checkout_date_end'))) {
|
||||
|
@ -656,22 +688,22 @@ class ReportsController extends Controller
|
|||
}
|
||||
|
||||
if (($request->filled('checkin_date_start'))) {
|
||||
$assets->whereBetween('last_checkin', [
|
||||
Carbon::parse($request->input('checkin_date_start'))->startOfDay(),
|
||||
// use today's date is `checkin_date_end` is not provided
|
||||
Carbon::parse($request->input('checkin_date_end', now()))->endOfDay(),
|
||||
]);
|
||||
$assets->whereBetween('last_checkin', [
|
||||
Carbon::parse($request->input('checkin_date_start'))->startOfDay(),
|
||||
// use today's date is `checkin_date_end` is not provided
|
||||
Carbon::parse($request->input('checkin_date_end', now()))->endOfDay(),
|
||||
]);
|
||||
}
|
||||
|
||||
if (($request->filled('expected_checkin_start')) && ($request->filled('expected_checkin_end'))) {
|
||||
$assets->whereBetween('assets.expected_checkin', [$request->input('expected_checkin_start'), $request->input('expected_checkin_end')]);
|
||||
$assets->whereBetween('assets.expected_checkin', [$request->input('expected_checkin_start'), $request->input('expected_checkin_end')]);
|
||||
}
|
||||
|
||||
if (($request->filled('last_audit_start')) && ($request->filled('last_audit_end'))) {
|
||||
$last_audit_start = \Carbon::parse($request->input('last_audit_start'))->startOfDay();
|
||||
$last_audit_end = \Carbon::parse($request->input('last_audit_end'))->endOfDay();
|
||||
$last_audit_start = \Carbon::parse($request->input('last_audit_start'))->startOfDay();
|
||||
$last_audit_end = \Carbon::parse($request->input('last_audit_end'))->endOfDay();
|
||||
|
||||
$assets->whereBetween('assets.last_audit_date', [$last_audit_start, $last_audit_end]);
|
||||
$assets->whereBetween('assets.last_audit_date', [$last_audit_start, $last_audit_end]);
|
||||
}
|
||||
|
||||
if (($request->filled('next_audit_start')) && ($request->filled('next_audit_end'))) {
|
||||
|
@ -742,7 +774,7 @@ class ReportsController extends Controller
|
|||
}
|
||||
|
||||
if ($request->filled('eol')) {
|
||||
$row[] = ($asset->purchase_date != '') ? $asset->present()->eol_date() : '';
|
||||
$row[] = ($asset->asset_eol_date) ? $asset->asset_eol_date : '';
|
||||
}
|
||||
|
||||
if ($request->filled('order')) {
|
||||
|
@ -826,6 +858,54 @@ class ReportsController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
if ($request->filled('phone')) {
|
||||
if ($asset->checkedOutToUser()) {
|
||||
$row[] = ($asset->assignedto) ? $asset->assignedto->phone : '';
|
||||
} else {
|
||||
$row[] = ''; // Empty string if unassigned
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->filled('user_address')) {
|
||||
if ($asset->checkedOutToUser()) {
|
||||
$row[] = ($asset->assignedto) ? $asset->assignedto->address : '';
|
||||
} else {
|
||||
$row[] = ''; // Empty string if unassigned
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->filled('user_city')) {
|
||||
if ($asset->checkedOutToUser()) {
|
||||
$row[] = ($asset->assignedto) ? $asset->assignedto->city : '';
|
||||
} else {
|
||||
$row[] = ''; // Empty string if unassigned
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->filled('user_state')) {
|
||||
if ($asset->checkedOutToUser()) {
|
||||
$row[] = ($asset->assignedto) ? $asset->assignedto->state : '';
|
||||
} else {
|
||||
$row[] = ''; // Empty string if unassigned
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->filled('user_country')) {
|
||||
if ($asset->checkedOutToUser()) {
|
||||
$row[] = ($asset->assignedto) ? $asset->assignedto->country : '';
|
||||
} else {
|
||||
$row[] = ''; // Empty string if unassigned
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->filled('user_zip')) {
|
||||
if ($asset->checkedOutToUser()) {
|
||||
$row[] = ($asset->assignedto) ? $asset->assignedto->zip : '';
|
||||
} else {
|
||||
$row[] = ''; // Empty string if unassigned
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->filled('status')) {
|
||||
$row[] = ($asset->assetstatus) ? $asset->assetstatus->name.' ('.$asset->present()->statusMeta.')' : '';
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ use App\Helpers\StorageHelper;
|
|||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Http\Requests\SettingsSamlRequest;
|
||||
use App\Http\Requests\SetupUserRequest;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\Group;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Asset;
|
||||
|
@ -26,7 +27,7 @@ use Response;
|
|||
use App\Http\Requests\SlackSettingsRequest;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Validator;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Settings for
|
||||
|
@ -809,9 +810,10 @@ class SettingsController extends Controller
|
|||
*/
|
||||
public function getLabels()
|
||||
{
|
||||
$setting = Setting::getSettings();
|
||||
|
||||
return view('settings.labels', compact('setting'));
|
||||
return view('settings.labels', [
|
||||
'setting' => Setting::getSettings(),
|
||||
'customFields' => CustomField::all(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1248,13 +1250,11 @@ class SettingsController extends Controller
|
|||
if (!$request->hasFile('file')) {
|
||||
return redirect()->route('settings.backups.index')->with('error', 'No file uploaded');
|
||||
} else {
|
||||
|
||||
$max_file_size = Helper::file_upload_max_size();
|
||||
|
||||
$rules = [
|
||||
$validator = Validator::make($request->all(), [
|
||||
'file' => 'required|mimes:zip|max:'.$max_file_size,
|
||||
];
|
||||
|
||||
$validator = \Validator::make($request->all(), $rules);
|
||||
]);
|
||||
|
||||
if ($validator->passes()) {
|
||||
|
||||
|
@ -1265,7 +1265,7 @@ class SettingsController extends Controller
|
|||
return redirect()->route('settings.backups.index')->with('success', 'File uploaded');
|
||||
}
|
||||
|
||||
return redirect()->route('settings.backups.index')->withErrors($request->getErrors());
|
||||
return redirect()->route('settings.backups.index')->withErrors($validator);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -125,10 +125,26 @@ class BulkUsersController extends Controller
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the user wants to actually blank out the values vs skip them
|
||||
*/
|
||||
if ($request->input('null_location_id')=='1') {
|
||||
$this->update_array['location_id'] = null;
|
||||
}
|
||||
|
||||
if ($request->input('null_department_id')=='1') {
|
||||
$this->update_array['department_id'] = null;
|
||||
}
|
||||
|
||||
if ($request->input('null_manager_id')=='1') {
|
||||
$this->update_array['manager_id'] = null;
|
||||
}
|
||||
|
||||
if ($request->input('null_company_id')=='1') {
|
||||
$this->update_array['company_id'] = null;
|
||||
}
|
||||
|
||||
|
||||
if (! $manager_conflict) {
|
||||
$this->conditionallyAddItem('manager_id');
|
||||
}
|
||||
|
|
|
@ -49,15 +49,19 @@ class LDAPImportController extends Controller
|
|||
{
|
||||
$this->authorize('update', User::class);
|
||||
// Call Artisan LDAP import command.
|
||||
$location_id = $request->input('location_id');
|
||||
Artisan::call('snipeit:ldap-sync', ['--location_id' => $location_id, '--json_summary' => true]);
|
||||
|
||||
Artisan::call('snipeit:ldap-sync', ['--location_id' => $request->input('location_id'), '--json_summary' => true]);
|
||||
|
||||
// Collect and parse JSON summary.
|
||||
$ldap_results_json = Artisan::output();
|
||||
$ldap_results = json_decode($ldap_results_json, true);
|
||||
if (!$ldap_results) {
|
||||
return redirect()->back()->withInput()->with('error', trans('general.no_results'));
|
||||
}
|
||||
|
||||
// Direct user to appropriate status page.
|
||||
if ($ldap_results['error']) {
|
||||
|
||||
return redirect()->back()->withInput()->with('error', $ldap_results['error_message']);
|
||||
}
|
||||
|
||||
|
|
46
app/Http/Requests/CustomAssetReportRequest.php
Normal file
46
app/Http/Requests/CustomAssetReportRequest.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
class CustomAssetReportRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'purchase_start' => 'date|date_format:Y-m-d|nullable',
|
||||
'purchase_end' => 'date|date_format:Y-m-d|nullable',
|
||||
'created_start' => 'date|date_format:Y-m-d|nullable',
|
||||
'created_end' => 'date|date_format:Y-m-d|nullable',
|
||||
'checkout_date_start' => 'date|date_format:Y-m-d|nullable',
|
||||
'checkout_date_end' => 'date|date_format:Y-m-d|nullable',
|
||||
'expected_checkin_start' => 'date|date_format:Y-m-d|nullable',
|
||||
'expected_checkin_end' => 'date|date_format:Y-m-d|nullable',
|
||||
'checkin_date_start' => 'date|date_format:Y-m-d|nullable',
|
||||
'checkin_date_end' => 'date|date_format:Y-m-d|nullable',
|
||||
'last_audit_start' => 'date|date_format:Y-m-d|nullable',
|
||||
'last_audit_end' => 'date|date_format:Y-m-d|nullable',
|
||||
'next_audit_start' => 'date|date_format:Y-m-d|nullable',
|
||||
'next_audit_end' => 'date|date_format:Y-m-d|nullable',
|
||||
];
|
||||
}
|
||||
|
||||
public function response(array $errors)
|
||||
{
|
||||
return $this->redirector->back()->withInput()->withErrors($errors, $this->errorBag);
|
||||
}
|
||||
}
|
40
app/Http/Requests/StoreAssetRequest.php
Normal file
40
app/Http/Requests/StoreAssetRequest.php
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Models\Asset;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
class StoreAssetRequest extends ImageUploadRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return Gate::allows('create', new Asset);
|
||||
}
|
||||
|
||||
public function prepareForValidation(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = array_merge(
|
||||
(new Asset)->getRules(),
|
||||
parent::rules(),
|
||||
);
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ namespace App\Http\Transformers;
|
|||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Company;
|
||||
|
@ -12,6 +13,7 @@ use App\Models\AssetModel;
|
|||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
class ActionlogsTransformer
|
||||
{
|
||||
|
@ -98,6 +100,13 @@ class ActionlogsTransformer
|
|||
\Log::debug('custom fields do not match');
|
||||
$clean_meta[$fieldname]['old'] = "************";
|
||||
$clean_meta[$fieldname]['new'] = "************";
|
||||
|
||||
// Display the changes if the user is an admin or superadmin
|
||||
if (Gate::allows('admin')) {
|
||||
$clean_meta[$fieldname]['old'] = ($enc_old) ? unserialize($enc_old): '';
|
||||
$clean_meta[$fieldname]['new'] = ($enc_new) ? unserialize($enc_new): '';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@ use App\Models\Asset;
|
|||
use App\Models\Setting;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Auth;
|
||||
|
||||
class AssetsTransformer
|
||||
{
|
||||
|
@ -38,7 +39,7 @@ class AssetsTransformer
|
|||
'byod' => ($asset->byod ? true : false),
|
||||
|
||||
'model_number' => (($asset->model) && ($asset->model->model_number)) ? e($asset->model->model_number) : null,
|
||||
'eol' => (($asset->model) && ($asset->model->eol != '')) ? $asset->model->eol : null,
|
||||
'eol' => (($asset->asset_eol_date != '') && ($asset->purchase_date != '')) ? Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date).' months' : null,
|
||||
'asset_eol_date' => ($asset->asset_eol_date != '') ? Helper::getFormattedDateObject($asset->asset_eol_date, 'date') : null,
|
||||
'status_label' => ($asset->assetstatus) ? [
|
||||
'id' => (int) $asset->assetstatus->id,
|
||||
|
@ -231,6 +232,29 @@ class AssetsTransformer
|
|||
'assigned_to_self' => ($asset->assigned_to == \Auth::user()->id),
|
||||
];
|
||||
|
||||
if (($asset->model) && ($asset->model->fieldset) && ($asset->model->fieldset->fields->count() > 0)) {
|
||||
$fields_array = [];
|
||||
|
||||
foreach ($asset->model->fieldset->fields as $field) {
|
||||
|
||||
// Only display this if it's allowed via the custom field setting
|
||||
if (($field->field_encrypted=='0') && ($field->show_in_requestable_list=='1')) {
|
||||
|
||||
$value = $asset->{$field->db_column};
|
||||
if (($field->format == 'DATE') && (!is_null($value)) && ($value != '')) {
|
||||
$value = Helper::getFormattedDateObject($value, 'date', false);
|
||||
}
|
||||
|
||||
$fields_array[$field->db_column] = e($value);
|
||||
}
|
||||
|
||||
$array['custom_fields'] = $fields_array;
|
||||
}
|
||||
} else {
|
||||
$array['custom_fields'] = new \stdClass; // HACK to force generation of empty object instead of empty list
|
||||
}
|
||||
|
||||
|
||||
$permissions_array['available_actions'] = [
|
||||
'cancel' => ($asset->isRequestedBy(\Auth::user())) ? true : false,
|
||||
'request' => ($asset->isRequestedBy(\Auth::user())) ? false : true,
|
||||
|
|
|
@ -34,7 +34,7 @@ class AccessoryImporter extends ItemImporter
|
|||
}
|
||||
|
||||
$this->log('Updating Accessory');
|
||||
$this->item['model_number'] = $this->findCsvMatch($row, "model_number");
|
||||
$this->item['model_number'] = trim($this->findCsvMatch($row, "model_number"));
|
||||
$accessory->update($this->sanitizeItemForUpdating($accessory));
|
||||
$accessory->save();
|
||||
|
||||
|
|
|
@ -5,6 +5,9 @@ namespace App\Importer;
|
|||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Statuslabel;
|
||||
use App\Models\User;
|
||||
use App\Events\CheckoutableCheckedIn;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class AssetImporter extends ItemImporter
|
||||
|
@ -80,13 +83,13 @@ class AssetImporter extends ItemImporter
|
|||
$this->log('No Matching Asset, Creating a new one');
|
||||
$asset = new Asset;
|
||||
}
|
||||
$this->item['notes'] = $this->findCsvMatch($row, 'asset_notes');
|
||||
$this->item['image'] = $this->findCsvMatch($row, 'image');
|
||||
$this->item['requestable'] = ($this->fetchHumanBoolean($this->findCsvMatch($row, 'requestable')) == 1) ? '1' : 0;
|
||||
$this->item['notes'] = trim($this->findCsvMatch($row, 'asset_notes'));
|
||||
$this->item['image'] = trim($this->findCsvMatch($row, 'image'));
|
||||
$this->item['requestable'] = trim(($this->fetchHumanBoolean($this->findCsvMatch($row, 'requestable'))) == 1) ? '1' : 0;
|
||||
$asset->requestable = $this->item['requestable'];
|
||||
$this->item['warranty_months'] = intval($this->findCsvMatch($row, 'warranty_months'));
|
||||
$this->item['warranty_months'] = intval(trim($this->findCsvMatch($row, 'warranty_months')));
|
||||
$this->item['model_id'] = $this->createOrFetchAssetModel($row);
|
||||
$this->item['byod'] = ($this->fetchHumanBoolean($this->findCsvMatch($row, 'byod')) == 1) ? '1' : 0;
|
||||
$this->item['byod'] = ($this->fetchHumanBoolean(trim($this->findCsvMatch($row, 'byod'))) == 1) ? '1' : 0;
|
||||
|
||||
|
||||
// If no status ID is found
|
||||
|
@ -141,7 +144,13 @@ class AssetImporter extends ItemImporter
|
|||
// If we have a target to checkout to, lets do so.
|
||||
//-- user_id is a property of the abstract class Importer, which this class inherits from and it's setted by
|
||||
//-- the class that needs to use it (command importer or GUI importer inside the project).
|
||||
if (isset($target)) {
|
||||
if (isset($target) && ($target !== false)) {
|
||||
if (!is_null($asset->assigned_to)){
|
||||
if ($asset->assigned_to != $target->id){
|
||||
event(new CheckoutableCheckedIn($asset, User::find($asset->assigned_to), Auth::user(), $asset->notes, date('Y-m-d H:i:s')));
|
||||
}
|
||||
}
|
||||
|
||||
$asset->fresh()->checkOut($target, $this->user_id, date('Y-m-d H:i:s'), null, $asset->notes, $asset->name);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,8 +28,8 @@ class ComponentImporter extends ItemImporter
|
|||
{
|
||||
$component = null;
|
||||
$this->log('Creating Component');
|
||||
$component = Component::where('name', $this->item['name'])
|
||||
->where('serial', $this->item['serial'])
|
||||
$component = Component::where('name', trim($this->item['name']))
|
||||
->where('serial', trim($this->item['serial']))
|
||||
->first();
|
||||
|
||||
if ($component) {
|
||||
|
|
|
@ -26,7 +26,7 @@ class ConsumableImporter extends ItemImporter
|
|||
*/
|
||||
public function createConsumableIfNotExists($row)
|
||||
{
|
||||
$consumable = Consumable::where('name', $this->item['name'])->first();
|
||||
$consumable = Consumable::where('name', trim($this->item['name']))->first();
|
||||
if ($consumable) {
|
||||
if (! $this->updating) {
|
||||
$this->log('A matching Consumable '.$this->item['name'].' already exists. ');
|
||||
|
@ -41,9 +41,9 @@ class ConsumableImporter extends ItemImporter
|
|||
}
|
||||
$this->log('No matching consumable, creating one');
|
||||
$consumable = new Consumable();
|
||||
$this->item['model_number'] = $this->findCsvMatch($row, 'model_number');
|
||||
$this->item['item_no'] = $this->findCsvMatch($row, 'item_number');
|
||||
$this->item['min_amt'] = $this->findCsvMatch($row, "min_amt");
|
||||
$this->item['model_number'] = trim($this->findCsvMatch($row, 'model_number'));
|
||||
$this->item['item_no'] = trim($this->findCsvMatch($row, 'item_number'));
|
||||
$this->item['min_amt'] = trim($this->findCsvMatch($row, "min_amt"));
|
||||
$consumable->fill($this->sanitizeItemForStoring($consumable));
|
||||
//FIXME: this disables model validation. Need to find a way to avoid double-logs without breaking everything.
|
||||
$consumable->unsetEventDispatcher();
|
||||
|
|
|
@ -19,22 +19,76 @@ abstract class Importer
|
|||
* Id of User performing import
|
||||
* @var
|
||||
*/
|
||||
|
||||
protected $user_id;
|
||||
/**
|
||||
* Are we updating items in the import
|
||||
* @var bool
|
||||
*/
|
||||
|
||||
protected $updating;
|
||||
|
||||
/**
|
||||
* Default Map of item fields->csv names
|
||||
*
|
||||
* This has been moved into app/Http/Livewire/Importer.php to be more granular.
|
||||
* @todo - remove references to this property since we don't use it anymore.
|
||||
* This private variable is ONLY used for the cli-importer.
|
||||
*
|
||||
* @todo - find a way to make this less duplicative
|
||||
* @var array
|
||||
*/
|
||||
private $defaultFieldMap = [
|
||||
|
||||
'asset_tag' => 'asset tag',
|
||||
'activated' => 'activated',
|
||||
'category' => 'category',
|
||||
'checkout_class' => 'checkout type', // Supports Location or User for assets. Using checkout_class instead of checkout_type because type exists on asset already.
|
||||
'checkout_location' => 'checkout location',
|
||||
'company' => 'company',
|
||||
'item_name' => 'item name',
|
||||
'item_number' => 'item number',
|
||||
'image' => 'image',
|
||||
'expiration_date' => 'expiration date',
|
||||
'location' => 'location',
|
||||
'notes' => 'notes',
|
||||
'license_email' => 'licensed to email',
|
||||
'license_name' => 'licensed to name',
|
||||
'maintained' => 'maintained',
|
||||
'manufacturer' => 'manufacturer',
|
||||
'asset_model' => 'model name',
|
||||
'model_number' => 'model number',
|
||||
'order_number' => 'order number',
|
||||
'purchase_cost' => 'purchase cost',
|
||||
'purchase_date' => 'purchase date',
|
||||
'purchase_order' => 'purchase order',
|
||||
'qty' => 'quantity',
|
||||
'reassignable' => 'reassignable',
|
||||
'requestable' => 'requestable',
|
||||
'seats' => 'seats',
|
||||
'serial' => 'serial number',
|
||||
'status' => 'status',
|
||||
'supplier' => 'supplier',
|
||||
'termination_date' => 'termination date',
|
||||
'warranty_months' => 'warranty',
|
||||
'full_name' => 'full name',
|
||||
'email' => 'email',
|
||||
'username' => 'username',
|
||||
'address' => 'address',
|
||||
'address2' => 'address2',
|
||||
'city' => 'city',
|
||||
'state' => 'state',
|
||||
'country' => 'country',
|
||||
'zip' => 'zip',
|
||||
'jobtitle' => 'job title',
|
||||
'employee_num' => 'employee number',
|
||||
'phone_number' => 'phone number',
|
||||
'first_name' => 'first name',
|
||||
'last_name' => 'last name',
|
||||
'department' => 'department',
|
||||
'manager_name' => 'manager full name',
|
||||
'manager_username' => 'manager username',
|
||||
'min_amt' => 'minimum quantity',
|
||||
'remote' => 'remote',
|
||||
'vip' => 'vip',
|
||||
];
|
||||
/**
|
||||
* Map of item fields->csv names
|
||||
|
@ -281,9 +335,11 @@ abstract class Importer
|
|||
$user_array['email'] = User::generateEmailFromFullName($user_array['full_name']);
|
||||
}
|
||||
|
||||
// Get some variables for $user_formatted_array in case we need them later
|
||||
$user_formatted_array = User::generateFormattedNameFromFullName($user_array['full_name'], Setting::getSettings()->username_format);
|
||||
|
||||
if (empty($user_array['first_name'])) {
|
||||
// Get some fields for first name and last name based off of full name
|
||||
$user_formatted_array = User::generateFormattedNameFromFullName($user_array['full_name'], Setting::getSettings()->username_format);
|
||||
$user_array['first_name'] = $user_formatted_array['first_name'];
|
||||
$user_array['last_name'] = $user_formatted_array['last_name'];
|
||||
}
|
||||
|
|
|
@ -372,7 +372,7 @@ class ItemImporter extends Importer
|
|||
if (empty($asset_statuslabel_name)) {
|
||||
return null;
|
||||
}
|
||||
$status = Statuslabel::where(['name' => $asset_statuslabel_name])->first();
|
||||
$status = Statuslabel::where(['name' => trim($asset_statuslabel_name)])->first();
|
||||
|
||||
if ($status) {
|
||||
$this->log('A matching Status '.$asset_statuslabel_name.' already exists');
|
||||
|
@ -381,7 +381,7 @@ class ItemImporter extends Importer
|
|||
}
|
||||
$this->log('Creating a new status');
|
||||
$status = new Statuslabel();
|
||||
$status->name = $asset_statuslabel_name;
|
||||
$status->name = trim($asset_statuslabel_name);
|
||||
|
||||
$status->deployable = 1;
|
||||
$status->pending = 0;
|
||||
|
@ -420,7 +420,7 @@ class ItemImporter extends Importer
|
|||
|
||||
//Otherwise create a manufacturer.
|
||||
$manufacturer = new Manufacturer();
|
||||
$manufacturer->name = $item_manufacturer;
|
||||
$manufacturer->name = trim($item_manufacturer);
|
||||
$manufacturer->user_id = $this->user_id;
|
||||
|
||||
if ($manufacturer->save()) {
|
||||
|
|
|
@ -55,19 +55,19 @@ class LicenseImporter extends ItemImporter
|
|||
$this->log('No Matching License, Creating a new one');
|
||||
$license = new License;
|
||||
}
|
||||
$asset_tag = $this->item['asset_tag'] = $this->findCsvMatch($row, 'asset_tag'); // used for checkout out to an asset.
|
||||
$asset_tag = $this->item['asset_tag'] = trim($this->findCsvMatch($row, 'asset_tag')); // used for checkout out to an asset.
|
||||
|
||||
$this->item["expiration_date"] = null;
|
||||
if ($this->findCsvMatch($row, "expiration_date")!='') {
|
||||
$this->item["expiration_date"] = date("Y-m-d 00:00:01", strtotime($this->findCsvMatch($row, "expiration_date")));
|
||||
$this->item["expiration_date"] = date("Y-m-d 00:00:01", strtotime(trim($this->findCsvMatch($row, "expiration_date"))));
|
||||
}
|
||||
$this->item['license_email'] = $this->findCsvMatch($row, 'license_email');
|
||||
$this->item['license_name'] = $this->findCsvMatch($row, 'license_name');
|
||||
$this->item['maintained'] = $this->findCsvMatch($row, 'maintained');
|
||||
$this->item['purchase_order'] = $this->findCsvMatch($row, 'purchase_order');
|
||||
$this->item['order_number'] = $this->findCsvMatch($row, 'order_number');
|
||||
$this->item['reassignable'] = $this->findCsvMatch($row, 'reassignable');
|
||||
$this->item['manufacturer'] = $this->createOrFetchManufacturer($this->findCsvMatch($row, 'manufacturer'));
|
||||
$this->item['license_email'] = trim($this->findCsvMatch($row, 'license_email'));
|
||||
$this->item['license_name'] = trim($this->findCsvMatch($row, 'license_name'));
|
||||
$this->item['maintained'] = trim($this->findCsvMatch($row, 'maintained'));
|
||||
$this->item['purchase_order'] = trim($this->findCsvMatch($row, 'purchase_order'));
|
||||
$this->item['order_number'] = trim($this->findCsvMatch($row, 'order_number'));
|
||||
$this->item['reassignable'] = trim($this->findCsvMatch($row, 'reassignable'));
|
||||
$this->item['manufacturer'] = $this->createOrFetchManufacturer(trim($this->findCsvMatch($row, 'manufacturer')));
|
||||
|
||||
if($this->item['reassignable'] == "")
|
||||
{
|
||||
|
|
|
@ -53,21 +53,21 @@ class LocationImporter extends ItemImporter
|
|||
}
|
||||
|
||||
// Pull the records from the CSV to determine their values
|
||||
$this->item['name'] = $this->findCsvMatch($row, 'name');
|
||||
$this->item['address'] = $this->findCsvMatch($row, 'address');
|
||||
$this->item['address2'] = $this->findCsvMatch($row, 'address2');
|
||||
$this->item['city'] = $this->findCsvMatch($row, 'city');
|
||||
$this->item['state'] = $this->findCsvMatch($row, 'state');
|
||||
$this->item['country'] = $this->findCsvMatch($row, 'country');
|
||||
$this->item['zip'] = $this->findCsvMatch($row, 'zip');
|
||||
$this->item['currency'] = $this->findCsvMatch($row, 'currency');
|
||||
$this->item['ldap_ou'] = $this->findCsvMatch($row, 'ldap_ou');
|
||||
$this->item['manager'] = $this->findCsvMatch($row, 'manager');
|
||||
$this->item['manager_username'] = $this->findCsvMatch($row, 'manager_username');
|
||||
$this->item['name'] = trim($this->findCsvMatch($row, 'name'));
|
||||
$this->item['address'] = trim($this->findCsvMatch($row, 'address'));
|
||||
$this->item['address2'] = trim($this->findCsvMatch($row, 'address2'));
|
||||
$this->item['city'] = trim($this->findCsvMatch($row, 'city'));
|
||||
$this->item['state'] = trim($this->findCsvMatch($row, 'state'));
|
||||
$this->item['country'] = trim($this->findCsvMatch($row, 'country'));
|
||||
$this->item['zip'] = trim($this->findCsvMatch($row, 'zip'));
|
||||
$this->item['currency'] = trim($this->findCsvMatch($row, 'currency'));
|
||||
$this->item['ldap_ou'] = trim($this->findCsvMatch($row, 'ldap_ou'));
|
||||
$this->item['manager'] = trim($this->findCsvMatch($row, 'manager'));
|
||||
$this->item['manager_username'] = trim($this->findCsvMatch($row, 'manager_username'));
|
||||
$this->item['user_id'] = \Auth::user()->id;
|
||||
|
||||
if ($this->findCsvMatch($row, 'parent_location')) {
|
||||
$this->item['parent_id'] = $this->createOrFetchLocation($this->findCsvMatch($row, 'parent_location'));
|
||||
$this->item['parent_id'] = $this->createOrFetchLocation(trim($this->findCsvMatch($row, 'parent_location')));
|
||||
}
|
||||
|
||||
if (!empty($this->item['manager'])) {
|
||||
|
|
|
@ -42,32 +42,32 @@ class UserImporter extends ItemImporter
|
|||
public function createUserIfNotExists(array $row)
|
||||
{
|
||||
// Pull the records from the CSV to determine their values
|
||||
$this->item['id'] = $this->findCsvMatch($row, 'id');
|
||||
$this->item['username'] = $this->findCsvMatch($row, 'username');
|
||||
$this->item['first_name'] = $this->findCsvMatch($row, 'first_name');
|
||||
$this->item['last_name'] = $this->findCsvMatch($row, 'last_name');
|
||||
$this->item['email'] = $this->findCsvMatch($row, 'email');
|
||||
$this->item['gravatar'] = $this->findCsvMatch($row, 'gravatar');
|
||||
$this->item['phone'] = $this->findCsvMatch($row, 'phone_number');
|
||||
$this->item['website'] = $this->findCsvMatch($row, 'website');
|
||||
$this->item['jobtitle'] = $this->findCsvMatch($row, 'jobtitle');
|
||||
$this->item['address'] = $this->findCsvMatch($row, 'address');
|
||||
$this->item['city'] = $this->findCsvMatch($row, 'city');
|
||||
$this->item['state'] = $this->findCsvMatch($row, 'state');
|
||||
$this->item['country'] = $this->findCsvMatch($row, 'country');
|
||||
$this->item['start_date'] = $this->findCsvMatch($row, 'start_date');
|
||||
$this->item['end_date'] = $this->findCsvMatch($row, 'end_date');
|
||||
$this->item['zip'] = $this->findCsvMatch($row, 'zip');
|
||||
$this->item['activated'] = ($this->fetchHumanBoolean($this->findCsvMatch($row, 'activated')) == 1) ? '1' : 0;
|
||||
$this->item['employee_num'] = $this->findCsvMatch($row, 'employee_num');
|
||||
$this->item['department_id'] = $this->createOrFetchDepartment($this->findCsvMatch($row, 'department'));
|
||||
$this->item['id'] = trim($this->findCsvMatch($row, 'id'));
|
||||
$this->item['username'] = trim($this->findCsvMatch($row, 'username'));
|
||||
$this->item['first_name'] = trim($this->findCsvMatch($row, 'first_name'));
|
||||
$this->item['last_name'] = trim($this->findCsvMatch($row, 'last_name'));
|
||||
$this->item['email'] = trim($this->findCsvMatch($row, 'email'));
|
||||
$this->item['gravatar'] = trim($this->findCsvMatch($row, 'gravatar'));
|
||||
$this->item['phone'] = trim($this->findCsvMatch($row, 'phone_number'));
|
||||
$this->item['website'] = trim($this->findCsvMatch($row, 'website'));
|
||||
$this->item['jobtitle'] = trim($this->findCsvMatch($row, 'jobtitle'));
|
||||
$this->item['address'] = trim($this->findCsvMatch($row, 'address'));
|
||||
$this->item['city'] = trim($this->findCsvMatch($row, 'city'));
|
||||
$this->item['state'] = trim($this->findCsvMatch($row, 'state'));
|
||||
$this->item['country'] = trim($this->findCsvMatch($row, 'country'));
|
||||
$this->item['start_date'] = trim($this->findCsvMatch($row, 'start_date'));
|
||||
$this->item['end_date'] = trim($this->findCsvMatch($row, 'end_date'));
|
||||
$this->item['zip'] = trim($this->findCsvMatch($row, 'zip'));
|
||||
$this->item['activated'] = ($this->fetchHumanBoolean(trim($this->findCsvMatch($row, 'activated'))) == 1) ? '1' : 0;
|
||||
$this->item['employee_num'] = trim($this->findCsvMatch($row, 'employee_num'));
|
||||
$this->item['department_id'] = trim($this->createOrFetchDepartment(trim($this->findCsvMatch($row, 'department'))));
|
||||
$this->item['manager_id'] = $this->fetchManager($this->findCsvMatch($row, 'manager_first_name'), $this->findCsvMatch($row, 'manager_last_name'));
|
||||
$this->item['remote'] =($this->fetchHumanBoolean($this->findCsvMatch($row, 'remote')) ==1 ) ? '1' : 0;
|
||||
$this->item['vip'] = ($this->fetchHumanBoolean($this->findCsvMatch($row, 'vip')) ==1 ) ? '1' : 0;
|
||||
$this->item['autoassign_licenses'] = ($this->fetchHumanBoolean($this->findCsvMatch($row, 'autoassign_licenses')) ==1 ) ? '1' : 0;
|
||||
$this->item['remote'] = ($this->fetchHumanBoolean(trim($this->findCsvMatch($row, 'remote'))) == 1 ) ? '1' : 0;
|
||||
$this->item['vip'] = ($this->fetchHumanBoolean(trim($this->findCsvMatch($row, 'vip'))) ==1 ) ? '1' : 0;
|
||||
$this->item['autoassign_licenses'] = ($this->fetchHumanBoolean(trim($this->findCsvMatch($row, 'autoassign_licenses'))) ==1 ) ? '1' : 0;
|
||||
|
||||
|
||||
$user_department = $this->findCsvMatch($row, 'department');
|
||||
$user_department = trim($this->findCsvMatch($row, 'department'));
|
||||
if ($this->shouldUpdateField($user_department)) {
|
||||
$this->item['department_id'] = $this->createOrFetchDepartment($user_department);
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ class Asset extends Depreciable
|
|||
|
||||
protected $rules = [
|
||||
'name' => 'max:255|nullable',
|
||||
'model_id' => 'required|integer|exists:models,id,deleted_at,NULL',
|
||||
'model_id' => 'required|integer|exists:models,id,deleted_at,NULL|not_array',
|
||||
'status_id' => 'required|integer|exists:status_labels,id',
|
||||
'company_id' => 'integer|nullable',
|
||||
'warranty_months' => 'numeric|nullable|digits_between:0,240',
|
||||
|
@ -100,7 +100,7 @@ class Asset extends Depreciable
|
|||
'expected_checkin' => 'date|nullable',
|
||||
'location_id' => 'exists:locations,id|nullable',
|
||||
'rtd_location_id' => 'exists:locations,id|nullable',
|
||||
'asset_tag' => 'required|min:1|max:255|unique_undeleted',
|
||||
'asset_tag' => 'required|min:1|max:255|unique_undeleted:assets,asset_tag',
|
||||
'purchase_date' => 'date|date_format:Y-m-d|nullable',
|
||||
'serial' => 'unique_serial|nullable',
|
||||
'purchase_cost' => 'numeric|nullable|gte:0',
|
||||
|
@ -212,16 +212,16 @@ class Asset extends Depreciable
|
|||
|
||||
$this->rules += $model->fieldset->validation_rules();
|
||||
|
||||
foreach ($this->model->fieldset->fields as $field){
|
||||
if($field->format == 'BOOLEAN'){
|
||||
$this->{$field->db_column} = filter_var($this->{$field->db_column}, FILTER_VALIDATE_BOOLEAN);
|
||||
if ($this->model->fieldset){
|
||||
foreach ($this->model->fieldset->fields as $field){
|
||||
if($field->format == 'BOOLEAN'){
|
||||
$this->{$field->db_column} = filter_var($this->{$field->db_column}, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return parent::save($params);
|
||||
}
|
||||
|
||||
|
@ -789,7 +789,6 @@ class Asset extends Depreciable
|
|||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the next autoincremented asset tag
|
||||
*
|
||||
|
@ -952,6 +951,7 @@ class Asset extends Depreciable
|
|||
->orWhere('assets_users.first_name', 'LIKE', '%'.$term.'%')
|
||||
->orWhere('assets_users.last_name', 'LIKE', '%'.$term.'%')
|
||||
->orWhere('assets_users.username', 'LIKE', '%'.$term.'%')
|
||||
->orWhere('assets_users.employee_num', 'LIKE', '%'.$term.'%')
|
||||
->orWhereMultipleColumns([
|
||||
'assets_users.first_name',
|
||||
'assets_users.last_name',
|
||||
|
|
|
@ -53,6 +53,12 @@ class CustomField extends Model
|
|||
'field_encrypted' => 'nullable|boolean',
|
||||
'auto_add_to_fieldsets' => 'boolean',
|
||||
'show_in_listview' => 'boolean',
|
||||
'show_in_requestable_list' => 'boolean',
|
||||
'show_in_email' => 'boolean',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'show_in_requestable_list' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -72,7 +78,8 @@ class CustomField extends Model
|
|||
'display_in_user_view',
|
||||
'auto_add_to_fieldsets',
|
||||
'show_in_listview',
|
||||
|
||||
'show_in_email',
|
||||
'show_in_requestable_list',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -243,8 +250,6 @@ class CustomField extends Model
|
|||
/**
|
||||
* Gets the DB column name.
|
||||
*
|
||||
* @todo figure out if this is still needed? I don't know WTF it's for.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.0]
|
||||
* @return string
|
||||
|
|
|
@ -92,6 +92,8 @@ class CustomFieldset extends Model
|
|||
|
||||
array_push($rule, $field->attributes['format']);
|
||||
$rules[$field->db_column_name()] = $rule;
|
||||
//add not_array to rules for all fields
|
||||
$rules[$field->db_column_name()][] = 'not_array';
|
||||
}
|
||||
|
||||
return $rules;
|
||||
|
|
|
@ -14,6 +14,14 @@ class FieldOption {
|
|||
|
||||
public function getValue(Asset $asset) {
|
||||
$dataPath = collect(explode('.', $this->dataSource));
|
||||
|
||||
// assignedTo directly on the asset is a special case where
|
||||
// we want to avoid returning the property directly
|
||||
// and instead return the entity's presented name.
|
||||
if ($dataPath[0] === 'assignedTo'){
|
||||
return $asset->assignedTo ? $asset->assignedTo->present()->fullName() : null;
|
||||
}
|
||||
|
||||
return $dataPath->reduce(function ($myValue, $path) {
|
||||
try { return $myValue ? $myValue->{$path} : ${$myValue}; }
|
||||
catch (\Exception $e) { return $myValue; }
|
||||
|
@ -46,4 +54,4 @@ class FieldOption {
|
|||
return $option;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ class License extends Depreciable
|
|||
protected $guarded = 'id';
|
||||
protected $table = 'licenses';
|
||||
|
||||
|
||||
protected $casts = [
|
||||
'purchase_date' => 'date',
|
||||
'expiration_date' => 'date',
|
||||
|
|
|
@ -92,6 +92,10 @@ class Setting extends Model
|
|||
'google_client_secret',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'label2_asset_logo' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the app settings.
|
||||
* Cache is expired on Setting model saved in EventServiceProvider.
|
||||
|
|
|
@ -26,7 +26,6 @@ class CheckinAccessoryNotification extends Notification
|
|||
$this->admin = $checkedInby;
|
||||
$this->note = $note;
|
||||
$this->settings = Setting::getSettings();
|
||||
\Log::debug('Constructor for notification fired');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Notifications;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
|
|
|
@ -11,7 +11,7 @@ use Carbon\Carbon;
|
|||
class AssetObserver
|
||||
{
|
||||
/**
|
||||
* Listen to the User created event.
|
||||
* Listen to the Asset updating event. This fires automatically every time an existing asset is saved.
|
||||
*
|
||||
* @param Asset $asset
|
||||
* @return void
|
||||
|
@ -137,14 +137,14 @@ class AssetObserver
|
|||
public function saving(Asset $asset)
|
||||
{
|
||||
// determine if calculated eol and then calculate it - this should only happen on a new asset
|
||||
if (is_null($asset->asset_eol_date) && !is_null($asset->purchase_date) && !is_null($asset->model->eol)){
|
||||
if (is_null($asset->asset_eol_date) && !is_null($asset->purchase_date) && ($asset->model->eol > 0)){
|
||||
$asset->asset_eol_date = $asset->purchase_date->addMonths($asset->model->eol)->format('Y-m-d');
|
||||
$asset->eol_explicit = false;
|
||||
}
|
||||
|
||||
// determine if explicit and set eol_explicit to true
|
||||
if (!is_null($asset->asset_eol_date) && !is_null($asset->purchase_date)) {
|
||||
if($asset->model->eol) {
|
||||
if($asset->model->eol > 0) {
|
||||
$months = Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date);
|
||||
if($months != $asset->model->eol) {
|
||||
$asset->eol_explicit = true;
|
||||
|
@ -153,7 +153,7 @@ class AssetObserver
|
|||
} elseif (!is_null($asset->asset_eol_date) && is_null($asset->purchase_date)) {
|
||||
$asset->eol_explicit = true;
|
||||
}
|
||||
if ((!is_null($asset->asset_eol_date)) && (!is_null($asset->purchase_date)) && (is_null($asset->model->eol))) {
|
||||
if ((!is_null($asset->asset_eol_date)) && (!is_null($asset->purchase_date)) && (is_null($asset->model->eol) || ($asset->model->eol == 0))) {
|
||||
$asset->eol_explicit = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ class AssetModelPresenter extends Presenter
|
|||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.eol'),
|
||||
'title' => trans('admin/hardware/form.eol_rate'),
|
||||
'visible' => true,
|
||||
],
|
||||
[
|
||||
|
|
|
@ -173,7 +173,7 @@ class AssetPresenter extends Presenter
|
|||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'visible' => false,
|
||||
'title' => trans('general.eol'),
|
||||
'title' => trans('admin/hardware/form.eol_rate'),
|
||||
],
|
||||
[
|
||||
'field' => 'asset_eol_date',
|
||||
|
|
|
@ -106,7 +106,7 @@ class LocationPresenter extends Presenter
|
|||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('admin/locations/table.address'),
|
||||
'title' => trans('admin/locations/table.address2'),
|
||||
'visible' => false,
|
||||
],
|
||||
[
|
||||
|
|
|
@ -48,6 +48,8 @@ class ValidationServiceProvider extends ServiceProvider
|
|||
// Unique only if undeleted
|
||||
// This works around the use case where multiple deleted items have the same unique attribute.
|
||||
// (I think this is a bug in Laravel's validator?)
|
||||
// $parameters is the rule parameters, like `unique_undeleted:users,id` - $parameters[0] is users, $parameters[1] is id
|
||||
// the UniqueUndeletedTrait prefills these so you can just use `unique_undeleted` in your rules (but this would only work directly in the model)
|
||||
Validator::extend('unique_undeleted', function ($attribute, $value, $parameters, $validator) {
|
||||
if (count($parameters)) {
|
||||
$count = DB::table($parameters[0])->select('id')->where($attribute, '=', $value)->whereNull('deleted_at')->where('id', '!=', $parameters[1])->count();
|
||||
|
@ -232,6 +234,10 @@ class ValidationServiceProvider extends ServiceProvider
|
|||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
Validator::extend('not_array', function ($attribute, $value, $parameters, $validator) {
|
||||
return !is_array($value);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -103,19 +103,12 @@ class Label implements View
|
|||
|
||||
$logo = null;
|
||||
|
||||
// Should we be trying to use a logo at all?
|
||||
if ($settings->label2_asset_logo='1') {
|
||||
|
||||
// If we don't have a company image, fall back to the general site label image
|
||||
if (!empty($settings->label_logo)) {
|
||||
$logo = Storage::disk('public')->path('/'.e($settings->label_logo));
|
||||
}
|
||||
|
||||
// If we have a company logo, use that first
|
||||
if (($asset->company) && ($asset->company->image!='')) {
|
||||
$logo = Storage::disk('public')->path('companies/'.e($asset->company->image));
|
||||
}
|
||||
|
||||
// Should we use the assets assigned company logo? (A.K.A. "Is `Labels > Use Asset Logo` enabled?"), and do we have a company logo?
|
||||
if ($settings->label2_asset_logo && $asset->company && $asset->company->image!='') {
|
||||
$logo = Storage::disk('public')->path('companies/'.e($asset->company->image));
|
||||
} elseif (!empty($settings->label_logo)) {
|
||||
// Use the general site label logo, if available
|
||||
$logo = Storage::disk('public')->path('/'.e($settings->label_logo));
|
||||
}
|
||||
|
||||
if (!empty($logo)) {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<?php
|
||||
return array (
|
||||
'app_version' => 'v6.2.3',
|
||||
'full_app_version' => 'v6.2.3 - build 11759-g8c4bf74f9',
|
||||
'build_version' => '11759',
|
||||
'full_app_version' => 'v6.2.3 - build 11936-gb47e734b3',
|
||||
'build_version' => '11936',
|
||||
'prerelease_version' => '',
|
||||
'hash_version' => 'g8c4bf74f9',
|
||||
'full_hash' => 'v6.2.3-42-g8c4bf74f9',
|
||||
'hash_version' => 'gb47e734b3',
|
||||
'full_hash' => 'v6.2.3-175-gb47e734b3',
|
||||
'branch' => 'develop',
|
||||
);
|
|
@ -38,7 +38,7 @@ class ActionlogFactory extends Factory
|
|||
{
|
||||
return $this->state(function () {
|
||||
$target = User::inRandomOrder()->first();
|
||||
$asset = Asset::RTD()->inRandomOrder()->first();
|
||||
$asset = Asset::inRandomOrder()->RTD()->first();
|
||||
|
||||
$asset->update(
|
||||
[
|
||||
|
|
|
@ -26,6 +26,7 @@ class CustomFieldFactory extends Factory
|
|||
'format' => '',
|
||||
'element' => 'text',
|
||||
'auto_add_to_fieldsets' => '0',
|
||||
'show_in_requestable_list' => '0',
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -66,6 +67,7 @@ class CustomFieldFactory extends Factory
|
|||
return [
|
||||
'name' => 'CPU',
|
||||
'help_text' => 'The speed of the processor on this device.',
|
||||
'show_in_requestable_list' => '1',
|
||||
];
|
||||
});
|
||||
}
|
||||
|
@ -79,4 +81,28 @@ class CustomFieldFactory extends Factory
|
|||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function testEncrypted()
|
||||
{
|
||||
return $this->state(function () {
|
||||
return [
|
||||
'name' => 'Test Encrypted',
|
||||
'field_encrypted' => '1',
|
||||
'help_text' => 'This is a sample encrypted field.',
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function testCheckbox()
|
||||
{
|
||||
return $this->state(function () {
|
||||
return [
|
||||
'name' => 'Test Checkbox',
|
||||
'help_text' => 'This is a sample checkbox.',
|
||||
'field_values' => "One\nTwo\nThree",
|
||||
'element' => 'checkbox',
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddShowInRequestableToCustomFields extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('custom_fields', function (Blueprint $table) {
|
||||
$table->boolean('show_in_requestable_list')->after('show_in_email')->nullable()->default(0);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('custom_fields', function (Blueprint $table) {
|
||||
if (Schema::hasColumn('custom_fields', 'show_in_requestable_list')) {
|
||||
$table->dropColumn('show_in_requestable_list');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -33,6 +33,9 @@ class CustomFieldSeeder extends Seeder
|
|||
CustomField::factory()->count(1)->ram()->create();
|
||||
CustomField::factory()->count(1)->cpu()->create();
|
||||
CustomField::factory()->count(1)->macAddress()->create();
|
||||
CustomField::factory()->count(1)->testEncrypted()->create();
|
||||
CustomField::factory()->count(1)->testCheckbox()->create();
|
||||
|
||||
|
||||
DB::table('custom_field_custom_fieldset')->insert([
|
||||
[
|
||||
|
@ -66,6 +69,33 @@ class CustomFieldSeeder extends Seeder
|
|||
'required' => 0,
|
||||
],
|
||||
|
||||
[
|
||||
'custom_field_id' => '6',
|
||||
'custom_fieldset_id' => '2',
|
||||
'order' => 0,
|
||||
'required' => 0,
|
||||
],
|
||||
|
||||
[
|
||||
'custom_field_id' => '6',
|
||||
'custom_fieldset_id' => '1',
|
||||
'order' => 0,
|
||||
'required' => 0,
|
||||
],
|
||||
|
||||
[
|
||||
'custom_field_id' => '7',
|
||||
'custom_fieldset_id' => '2',
|
||||
'order' => 0,
|
||||
'required' => 0,
|
||||
],
|
||||
[
|
||||
'custom_field_id' => '7',
|
||||
'custom_fieldset_id' => '1',
|
||||
'order' => 0,
|
||||
'required' => 0,
|
||||
],
|
||||
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,12 +38,13 @@ class DatabaseSeeder extends Seeder
|
|||
$this->call(DepreciationSeeder::class);
|
||||
$this->call(StatuslabelSeeder::class);
|
||||
$this->call(AccessorySeeder::class);
|
||||
$this->call(CustomFieldSeeder::class);
|
||||
$this->call(AssetSeeder::class);
|
||||
$this->call(LicenseSeeder::class);
|
||||
$this->call(ComponentSeeder::class);
|
||||
$this->call(ConsumableSeeder::class);
|
||||
$this->call(ActionlogSeeder::class);
|
||||
$this->call(CustomFieldSeeder::class);
|
||||
|
||||
|
||||
Artisan::call('snipeit:sync-asset-locations', ['--output' => 'all']);
|
||||
$output = Artisan::output();
|
||||
|
|
|
@ -9,7 +9,7 @@ services:
|
|||
ports:
|
||||
- "8000:80"
|
||||
volumes:
|
||||
- ./logs:/var/www/html/storage/logs
|
||||
- ./storage/logs:/var/www/html/storage/logs
|
||||
depends_on:
|
||||
- mariadb
|
||||
- redis
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
return array(
|
||||
|
||||
'does_not_exist' => 'The accessory [:id] does not exist.',
|
||||
'not_found' => 'That accessory was not found.',
|
||||
'assoc_users' => 'This accessory currently has :count items checked out to users. Please check in the accessories and and try again. ',
|
||||
|
||||
'create' => array(
|
||||
|
|
|
@ -34,7 +34,8 @@ return [
|
|||
'create_field' => 'New Custom Field',
|
||||
'create_field_title' => 'Create a new custom field',
|
||||
'value_encrypted' => 'The value of this field is encrypted in the database. Only admin users will be able to view the decrypted value',
|
||||
'show_in_email' => 'Include the value of this field in checkout emails sent to the user? Encrypted fields cannot be included in emails.',
|
||||
'show_in_email' => 'Include the value of this field in checkout emails sent to the user? Encrypted fields cannot be included in emails',
|
||||
'show_in_email_short' => 'Include in emails.',
|
||||
'help_text' => 'Help Text',
|
||||
'help_text_description' => 'This is optional text that will appear below the form elements while editing an asset to provide context on the field.',
|
||||
'about_custom_fields_title' => 'About Custom Fields',
|
||||
|
@ -51,7 +52,10 @@ return [
|
|||
'display_in_user_view_table' => 'Visible to User',
|
||||
'auto_add_to_fieldsets' => 'Automatically add this to every new fieldset',
|
||||
'add_to_preexisting_fieldsets' => 'Add to any existing fieldsets',
|
||||
'show_in_listview' => 'Show in list views by default. Authorized users will still be able to show/hide via the column selector.',
|
||||
'show_in_listview' => 'Show in list views by default. Authorized users will still be able to show/hide via the column selector',
|
||||
'show_in_listview_short' => 'Show in lists',
|
||||
'show_in_requestable_list_short' => 'Show in requestable assets list',
|
||||
'show_in_requestable_list' => 'Show value in requestable assets list. Encrypted fields will not be shown',
|
||||
'encrypted_options' => 'This field is encrypted, so some display options will not be available.',
|
||||
|
||||
];
|
||||
|
|
|
@ -49,6 +49,7 @@ return [
|
|||
'asset_location' => 'Update Asset Location',
|
||||
'asset_location_update_default_current' => 'Update default location AND actual location',
|
||||
'asset_location_update_default' => 'Update only default location',
|
||||
'asset_location_update_actual' => 'Update only actual location',
|
||||
'asset_not_deployable' => 'That asset status is not deployable. This asset cannot be checked out.',
|
||||
'asset_deployable' => 'That status is deployable. This asset can be checked out.',
|
||||
'processing_spinner' => 'Processing... (This might take a bit of time on large files)',
|
||||
|
|
|
@ -11,6 +11,7 @@ return [
|
|||
'create' => [
|
||||
'error' => 'Asset was not created, please try again. :(',
|
||||
'success' => 'Asset created successfully. :)',
|
||||
'success_linked' => 'Asset with tag :tag was created successfully. <strong><a href=":link" style="color: white;">Click here to view</a></strong>.',
|
||||
],
|
||||
|
||||
'update' => [
|
||||
|
|
|
@ -15,6 +15,7 @@ return [
|
|||
'print_all_assigned' => 'Print All Assigned',
|
||||
'name' => 'Location Name',
|
||||
'address' => 'Address',
|
||||
'address2' => 'Address Line 2',
|
||||
'zip' => 'Postal Code',
|
||||
'locations' => 'Locations',
|
||||
'parent' => 'Parent',
|
||||
|
|
|
@ -6,5 +6,12 @@ return [
|
|||
'send_reminder' => 'Send reminder',
|
||||
'reminder_sent' => 'Reminder sent',
|
||||
'acceptance_deleted' => 'Acceptance request deleted',
|
||||
'acceptance_request' => 'Acceptance request'
|
||||
'acceptance_request' => 'Acceptance request',
|
||||
'custom_export' => [
|
||||
'user_address' => 'User Address',
|
||||
'user_city' => 'User City',
|
||||
'user_state' => 'User State',
|
||||
'user_country' => 'User Country',
|
||||
'user_zip' => 'User Zip'
|
||||
]
|
||||
];
|
|
@ -8,6 +8,7 @@ return array(
|
|||
'user_exists' => 'User already exists!',
|
||||
'user_not_found' => 'User does not exist.',
|
||||
'user_login_required' => 'The login field is required',
|
||||
'user_has_no_assets_assigned' => 'No assets currently assigned to user.',
|
||||
'user_password_required' => 'The password is required.',
|
||||
'insufficient_permissions' => 'Insufficient Permissions.',
|
||||
'user_deleted_warning' => 'This user has been deleted. You will have to restore this user to edit them or assign them new assets.',
|
||||
|
|
|
@ -368,7 +368,7 @@ return [
|
|||
'consumables_count' => 'Consumables Count',
|
||||
'components_count' => 'Components Count',
|
||||
'licenses_count' => 'Licenses Count',
|
||||
'notification_error' => 'Error:',
|
||||
'notification_error' => 'Error',
|
||||
'notification_error_hint' => 'Please check the form below for errors',
|
||||
'notification_bulk_error_hint' => 'The following fields had validation errors and were not edited:',
|
||||
'notification_success' => 'Success',
|
||||
|
|
|
@ -30,5 +30,6 @@ return [
|
|||
'consumables' => 'Consumables are anything purchased that will be used up over time. For example, printer ink or copier paper.',
|
||||
|
||||
'depreciations' => 'You can set up asset depreciations to depreciate assets based on straight-line depreciation.',
|
||||
|
||||
|
||||
'empty_file' => 'The importer detects that this file is empty.'
|
||||
];
|
||||
|
|
|
@ -95,6 +95,7 @@ return [
|
|||
'url' => 'The :attribute format is invalid.',
|
||||
'unique_undeleted' => 'The :attribute must be unique.',
|
||||
'non_circular' => 'The :attribute must not create a circular reference.',
|
||||
'not_array' => 'The :attribute field cannot be an array.',
|
||||
'disallow_same_pwd_as_user_fields' => 'Password cannot be the same as the username.',
|
||||
'letters' => 'Password must contain at least one letter.',
|
||||
'numbers' => 'Password must contain at least one number.',
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
data-side-pagination="client"
|
||||
data-show-columns="true"
|
||||
data-show-export="true"
|
||||
data-show-refresh="true"
|
||||
data-show-refresh="false"
|
||||
data-sort-order="asc"
|
||||
id="pendingAcceptances"
|
||||
class="table table-striped snipe-table"
|
||||
|
|
|
@ -65,6 +65,12 @@
|
|||
<th class="col-md-2" data-field="location" data-sortable="true">{{ trans('admin/hardware/table.location') }}</th>
|
||||
<th class="col-md-2" data-field="status" data-sortable="true">{{ trans('admin/hardware/table.status') }}</th>
|
||||
<th class="col-md-2" data-field="expected_checkin" data-formatter="dateDisplayFormatter" data-sortable="true">{{ trans('admin/hardware/form.expected_checkin') }}</th>
|
||||
|
||||
@foreach(\App\Models\CustomField::get() as $field)
|
||||
@if (($field->field_encrypted=='0') && ($field->show_in_requestable_list=='1'))
|
||||
<th class="col-md-2" data-field="custom_fields.{{ $field->db_column }}" data-sortable="true">{{ $field->name }}</th>
|
||||
@endif
|
||||
@endforeach
|
||||
<th class="col-md-1" data-formatter="assetRequestActionsFormatter" data-field="actions" data-sortable="false">{{ trans('table.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
|
@ -32,13 +32,19 @@
|
|||
}'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-md-1" data-field="image" data-formatter="imageFormatter">{{ trans('general.image') }}</th>
|
||||
<th class="col-md-2" data-field="name">{{ trans('general.item_name') }}</th>
|
||||
<th class="col-md-2" data-field="type">{{ trans('general.type') }}</th>
|
||||
<th class="col-md-2" data-field="qty">{{ trans('general.qty') }}</th>
|
||||
<th class="col-md-2" data-field="location">{{ trans('admin/hardware/table.location') }}</th>
|
||||
<th class="col-md-2" data-field="expected_checkin" data-formatter="dateDisplayFormatter"> {{ trans('admin/hardware/form.expected_checkin') }}</th>
|
||||
<th class="col-md-2" data-field="request_date" data-formatter="dateDisplayFormatter"> {{ trans('general.requested_date') }}</th>
|
||||
<th data-field="image" data-formatter="imageFormatter">{{ trans('general.image') }}</th>
|
||||
<th data-field="name">{{ trans('general.item_name') }}</th>
|
||||
<th data-field="type">{{ trans('general.type') }}</th>
|
||||
<th data-field="qty">{{ trans('general.qty') }}</th>
|
||||
<th data-field="location">{{ trans('admin/hardware/table.location') }}</th>
|
||||
<th data-field="expected_checkin" data-formatter="dateDisplayFormatter"> {{ trans('admin/hardware/form.expected_checkin') }}</th>
|
||||
<th data-field="request_date" data-formatter="dateDisplayFormatter"> {{ trans('general.requested_date') }}</th>
|
||||
|
||||
@foreach(\App\Models\CustomField::get() as $field)
|
||||
@if (($field->field_encrypted=='0') && ($field->show_in_requestable_list=='1'))
|
||||
<th data-field="custom_fields.{{ $field->db_column }}">{{ $field->name }}</th>
|
||||
@endif
|
||||
@endforeach
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
|
|
|
@ -388,7 +388,7 @@
|
|||
data-show-columns="true"
|
||||
data-show-export="true"
|
||||
data-show-footer="true"
|
||||
data-show-refresh="true"
|
||||
data-show-refresh="false"
|
||||
data-sort-order="asc"
|
||||
id="userAssets"
|
||||
class="table table-striped snipe-table"
|
||||
|
@ -478,7 +478,7 @@
|
|||
data-side-pagination="client"
|
||||
data-show-columns="true"
|
||||
data-show-export="true"
|
||||
data-show-refresh="true"
|
||||
data-show-refresh="false"
|
||||
data-sort-order="asc"
|
||||
id="userLicenses"
|
||||
class="table table-striped snipe-table"
|
||||
|
@ -525,7 +525,7 @@
|
|||
data-show-fullscreen="true"
|
||||
data-show-export="true"
|
||||
data-show-footer="true"
|
||||
data-show-refresh="true"
|
||||
data-show-refresh="false"
|
||||
data-sort-order="asc"
|
||||
data-sort-name="name"
|
||||
class="table table-striped snipe-table table-hover"
|
||||
|
@ -576,7 +576,7 @@
|
|||
data-show-fullscreen="true"
|
||||
data-show-export="true"
|
||||
data-show-footer="true"
|
||||
data-show-refresh="true"
|
||||
data-show-refresh="false"
|
||||
data-sort-order="asc"
|
||||
data-sort-name="name"
|
||||
class="table table-striped snipe-table table-hover"
|
||||
|
|
|
@ -88,7 +88,7 @@
|
|||
}
|
||||
@endphp
|
||||
<div class="col-md-8 required">
|
||||
{{ Form::select("format",Helper::predefined_formats(), ($field_format == '') ? $field->format : $field_format, array('class'=>'format select2 form-control', 'aria-label'=>'format')) }}
|
||||
{{ Form::select("format",Helper::predefined_formats(), ($field_format == '') ? $field->format : $field_format, array('class'=>'format select2 form-control', 'aria-label'=>'format', 'style' => 'width:100%;')) }}
|
||||
{!! $errors->first('format', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -118,10 +118,40 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Set up checkbox form group -->
|
||||
<div class="form-group">
|
||||
|
||||
<!-- Encrypted warning callout box -->
|
||||
@if (($field->id) && ($field->field_encrypted=='1'))
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
<div class="alert alert-warning fade in">
|
||||
<i class="fas fa-exclamation-triangle faa-pulse animated"></i>
|
||||
<strong>{{ trans('general.notification_warning') }}:</strong>
|
||||
{{ trans('admin/custom_fields/general.encrypted_options') }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (!$field->id)
|
||||
<!-- Encrypted -->
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
<label class="form-control">
|
||||
<input type="checkbox" value="1" name="field_encrypted" id="field_encrypted"{{ (Request::old('field_encrypted') || $field->field_encrypted) ? ' checked="checked"' : '' }}>
|
||||
{{ trans('admin/custom_fields/general.encrypt_field') }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-md-9 col-md-offset-3" id="encrypt_warning" style="display:none;">
|
||||
<div class="callout callout-danger">
|
||||
<p><i class="fas fa-exclamation-triangle" aria-hidden="true"></i> {{ trans('admin/custom_fields/general.encrypt_field_help') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endif
|
||||
|
||||
|
||||
|
||||
<!-- Auto-Add to Future Fieldsets -->
|
||||
<div class="form-group {{ $errors->has('auto_add_to_fieldsets') ? ' has-error' : '' }}" id="auto_add_to_fieldsets">
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
<label class="form-control">
|
||||
<input type="checkbox" name="auto_add_to_fieldsets" aria-label="auto_add_to_fieldsets" value="1"{{ (old('auto_add_to_fieldsets') || $field->auto_add_to_fieldsets) ? ' checked="checked"' : '' }}>
|
||||
|
@ -129,6 +159,7 @@
|
|||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Show in list view -->
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
<label class="form-control">
|
||||
<input type="checkbox" name="show_in_listview" aria-label="show_in_listview" value="1"{{ (old('show_in_listview') || $field->show_in_listview) ? ' checked="checked"' : '' }}>
|
||||
|
@ -136,45 +167,43 @@
|
|||
</label>
|
||||
</div>
|
||||
|
||||
@if (!$field->id)
|
||||
<!-- Encrypted -->
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
<label class="form-control">
|
||||
<input type="checkbox" value="1" name="field_encrypted" id="field_encrypted"{{ (Request::old('field_encrypted') || $field->field_encrypted) ? ' checked="checked"' : '' }}>
|
||||
{{ trans('admin/custom_fields/general.encrypt_field') }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="col-md-9 col-md-offset-3" id="encrypt_warning" style="display:none;">
|
||||
<div class="callout callout-danger">
|
||||
<p><i class="fas fa-exclamation-triangle" aria-hidden="true"></i> {{ trans('admin/custom_fields/general.encrypt_field_help') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@if ((!$field->id) || ($field->field_encrypted=='0'))
|
||||
|
||||
<!-- Show in requestable list view -->
|
||||
<div class="col-md-9 col-md-offset-3" id="show_in_requestable_list">
|
||||
<label class="form-control">
|
||||
<input type="checkbox" name="show_in_requestable_list" aria-label="show_in_requestable_list" value="1"{{ (old('show_in_requestable_list') || $field->show_in_requestable_list) ? ' checked="checked"' : '' }}>
|
||||
{{ trans('admin/custom_fields/general.show_in_requestable_list') }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Show in Email -->
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
<div class="col-md-9 col-md-offset-3" id="show_in_email">
|
||||
<label class="form-control">
|
||||
<input type="checkbox" name="show_in_email" aria-label="show_in_email" value="1"{{ (old('show_in_email') || $field->show_in_email) ? ' checked="checked"' : '' }}>
|
||||
{{ trans('admin/custom_fields/general.show_in_email') }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Value Must be Unique -->
|
||||
<div class="col-md-9 col-md-offset-3" id="is_unique">
|
||||
<label class="form-control">
|
||||
<input type="checkbox" name="is_unique" aria-label="is_unique" value="1"{{ (old('is_unique') || $field->is_unique) ? ' checked="checked"' : '' }}>
|
||||
{{ trans('admin/custom_fields/general.is_unique') }}
|
||||
</label>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Show in View All Assets profile view -->
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
<div class="col-md-9 col-md-offset-3" id="display_in_user_view">
|
||||
<label class="form-control">
|
||||
<input type="checkbox" name="display_in_user_view" aria-label="display_in_user_view" value="1" {{ (old('display_in_user_view') || $field->display_in_user_view) ? ' checked="checked"' : '' }}>
|
||||
{{ trans('admin/custom_fields/general.display_in_user_view') }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Value Must be Unique -->
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
<label class="form-control">
|
||||
<input type="checkbox" name="is_unique" aria-label="is_unique" value="1"{{ (old('is_unique') || $field->is_unique) ? ' checked="checked"' : '' }}>
|
||||
{{ trans('admin/custom_fields/general.is_unique') }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -287,11 +316,13 @@
|
|||
$("#show_in_email").hide();
|
||||
$("#display_in_user_view").hide();
|
||||
$("#is_unique").hide();
|
||||
$("#show_in_requestable_list").hide();
|
||||
} else {
|
||||
$("#encrypt_warning").hide();
|
||||
$("#show_in_email").show();
|
||||
$("#display_in_user_view").show();
|
||||
$("#is_unique").show();
|
||||
$("#show_in_requestable_list").show();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -145,12 +145,14 @@
|
|||
<th data-sortable="true"><i class="fa fa-lock" aria-hidden="true"></i>
|
||||
<span class="hidden-xs hidden-sm hidden-md hidden-lg">{{ trans('admin/custom_fields/general.encrypted') }}</span>
|
||||
</th>
|
||||
<th data-sortable="true"><i class="fa fa-list" aria-hidden="true"></i>
|
||||
<th data-sortable="true" class="text-center"><i class="fa fa-list" aria-hidden="true"></i>
|
||||
<span class="hidden-xs hidden-sm hidden-md hidden-lg">{{ trans('admin/custom_fields/general.show_in_listview_short') }}</span>
|
||||
</th>
|
||||
<th data-visible="false" data-sortable="true"><i class="fa fa-eye" aria-hidden="true"><span class="sr-only">Visible to User</span></i></th>
|
||||
<th data-sortable="true" data-searchable="true"><i class="fa fa-envelope" aria-hidden="true"><span class="sr-only">Show in Email</span></i></th>
|
||||
<th data-sortable="true" data-searchable="true">{{ trans('admin/custom_fields/general.field_element_short') }}</th>
|
||||
<th data-visible="false" data-sortable="true" class="text-center"><i class="fa fa-eye" aria-hidden="true"><span class="sr-only">Visible to User</span></i></th>
|
||||
<th data-sortable="true" data-searchable="true" class="text-center"><i class="fa fa-envelope" aria-hidden="true"><span class="sr-only">{{ trans('admin/custom_fields/general.show_in_email_short') }}</span></i></th>
|
||||
<th data-sortable="true" data-searchable="true" class="text-center"><i class="fa fa-laptop fa-fw" aria-hidden="true"><span class="sr-only">{{ trans('admin/custom_fields/general.show_in_requestable_list_short') }}</span></i></th>
|
||||
<th data-sortable="true" data-searchable="true" class="text-center"><i class="fa-solid fa-fingerprint"><span class="sr-only">{{ trans('admin/custom_fields/general.unique') }}</span></i></th>
|
||||
<th data-sortable="true" data-searchable="true" class="text-center">{{ trans('admin/custom_fields/general.field_element_short') }}</th>
|
||||
<th data-searchable="true">{{ trans('admin/custom_fields/general.fieldsets') }}</th>
|
||||
<th>{{ trans('button.actions') }}</th>
|
||||
</tr>
|
||||
|
@ -161,7 +163,7 @@
|
|||
<td>{{ $field->name }}</td>
|
||||
<td>{{ $field->help_text }}</td>
|
||||
|
||||
<td class='text-center'>{!! ($field->is_unique=='1') ? '<i class="fas fa-check text-success" aria-hidden="true"><span class="sr-only">'.trans('general.yes').'</span></i>' : '<i class="fas fa-times text-danger" aria-hidden="true"><span class="sr-only">'.trans('general.no').'</span></i>' !!}</td>
|
||||
<td class="text-center">{!! ($field->is_unique=='1') ? '<i class="fas fa-check text-success" aria-hidden="true"><span class="sr-only">'.trans('general.yes').'</span></i>' : '<i class="fas fa-times text-danger" aria-hidden="true"><span class="sr-only">'.trans('general.no').'</span></i>' !!}</td>
|
||||
<td>
|
||||
<code>{{ $field->convertUnicodeDbSlug() }}</code>
|
||||
@if ($field->convertUnicodeDbSlug()!=$field->db_column)
|
||||
|
@ -170,10 +172,12 @@
|
|||
@endif
|
||||
</td>
|
||||
<td>{{ $field->format }}</td>
|
||||
<td>{!! ($field->field_encrypted=='1' ? '<i class="fa fa-check text-success"></i>' : '<i class="fa fa-times text-danger"></i>') !!}</td>
|
||||
<td>{!! ($field->show_in_listview=='1' ? '<i class="fa fa-check text-success"></i>' : '<i class="fa fa-times text-danger"></i>') !!}</td>
|
||||
<td>{!! ($field->display_in_user_view=='1' ? '<i class="fa fa-check text-success"></i>' : '<i class="fa fa-times text-danger"></i>') !!}</td>
|
||||
<td class='text-center'>{!! ($field->show_in_email=='1') ? '<i class="fas fa-check text-success" aria-hidden="true"><span class="sr-only">'.trans('general.yes').'</span></i>' : '<i class="fas fa-times text-danger" aria-hidden="true"><span class="sr-only">'.trans('general.no').'</span></i>' !!}</td>
|
||||
<td class="text-center">{!! ($field->field_encrypted=='1' ? '<i class="fa fa-check text-success"></i>' : '<i class="fa fa-times text-danger"></i>') !!}</td>
|
||||
<td class="text-center">{!! ($field->show_in_listview=='1' ? '<i class="fa fa-check text-success"></i>' : '<i class="fa fa-times text-danger"></i>') !!}</td>
|
||||
<td class="text-center">{!! ($field->display_in_user_view=='1' ? '<i class="fa fa-check text-success"></i>' : '<i class="fa fa-times text-danger"></i>') !!}</td>
|
||||
<td class="text-center">{!! ($field->show_in_email=='1') ? '<i class="fas fa-check text-success" aria-hidden="true"><span class="sr-only">'.trans('general.yes').'</span></i>' : '<i class="fas fa-times text-danger" aria-hidden="true"><span class="sr-only">'.trans('general.no').'</span></i>' !!}</td>
|
||||
<td class="text-center">{!! ($field->show_in_requestable_list=='1') ? '<i class="fas fa-check text-success" aria-hidden="true"><span class="sr-only">'.trans('general.yes').'</span></i>' : '<i class="fas fa-times text-danger" aria-hidden="true"><span class="sr-only">'.trans('general.no').'</span></i>' !!}</td>
|
||||
<td class="text-center">{!! ($field->is_unique=='1') ? '<i class="fas fa-check text-success" aria-hidden="true"><span class="sr-only">'.trans('general.yes').'</span></i>' : '<i class="fas fa-times text-danger" aria-hidden="true"><span class="sr-only">'.trans('general.no').'</span></i>' !!}</td>
|
||||
<td>{{ $field->element }}</td>
|
||||
<td>
|
||||
@foreach($field->fieldset as $fieldset)
|
||||
|
|
|
@ -274,63 +274,136 @@
|
|||
</div> <!--/row-->
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<!-- Locations -->
|
||||
<div class="box box-default">
|
||||
<div class="box-header with-border">
|
||||
<h2 class="box-title">{{ trans('general.asset') }} {{ trans('general.locations') }}</h2>
|
||||
<div class="box-tools pull-right">
|
||||
<button type="button" class="btn btn-box-tool" data-widget="collapse">
|
||||
<i class="fas fa-minus" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.collapse') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="table-responsive">
|
||||
<table
|
||||
data-cookie-id-table="dashLocationSummary"
|
||||
data-height="400"
|
||||
data-pagination="true"
|
||||
data-side-pagination="server"
|
||||
data-sort-order="desc"
|
||||
data-sort-field="assets_count"
|
||||
id="dashLocationSummary"
|
||||
class="table table-striped snipe-table"
|
||||
data-url="{{ route('api.locations.index', ['sort' => 'assets_count', 'order' => 'asc']) }}">
|
||||
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-sm-3" data-visible="true" data-field="name" data-formatter="locationsLinkFormatter" data-sortable="true">{{ trans('general.name') }}</th>
|
||||
|
||||
<th class="col-sm-1" data-visible="true" data-field="assets_count" data-sortable="true">
|
||||
<i class="fas fa-barcode" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.asset_count') }}</span>
|
||||
</th>
|
||||
<th class="col-sm-1" data-visible="true" data-field="assigned_assets_count" data-sortable="true">
|
||||
|
||||
{{ trans('general.assigned') }}
|
||||
</th>
|
||||
<th class="col-sm-1" data-visible="true" data-field="users_count" data-sortable="true">
|
||||
<i class="fas fa-users" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.people') }}</span>
|
||||
|
||||
</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div> <!-- /.col -->
|
||||
<div class="text-center col-md-12" style="padding-top: 10px;">
|
||||
<a href="{{ route('locations.index') }}" class="btn btn-primary btn-sm" style="width: 100%">{{ trans('general.viewall') }}</a>
|
||||
</div>
|
||||
</div> <!-- /.row -->
|
||||
@if ($snipeSettings->full_multiple_companies_support=='1')
|
||||
<!-- Companies -->
|
||||
<div class="box box-default">
|
||||
<div class="box-header with-border">
|
||||
<h2 class="box-title">{{ trans('general.companies') }}</h2>
|
||||
<div class="box-tools pull-right">
|
||||
<button type="button" class="btn btn-box-tool" data-widget="collapse">
|
||||
<i class="fas fa-minus" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.collapse') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="table-responsive">
|
||||
<table
|
||||
data-cookie-id-table="dashCompanySummary"
|
||||
data-height="400"
|
||||
data-pagination="true"
|
||||
data-side-pagination="server"
|
||||
data-sort-order="desc"
|
||||
data-sort-field="assets_count"
|
||||
id="dashCompanySummary"
|
||||
class="table table-striped snipe-table"
|
||||
data-url="{{ route('api.companies.index', ['sort' => 'assets_count', 'order' => 'asc']) }}">
|
||||
|
||||
</div><!-- /.box-body -->
|
||||
</div> <!-- /.box -->
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-sm-3" data-visible="true" data-field="name" data-formatter="companiesLinkFormatter" data-sortable="true">{{ trans('general.name') }}</th>
|
||||
<th class="col-sm-1" data-visible="true" data-field="users_count" data-sortable="true">
|
||||
<i class="fas fa-users" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.people') }}</span>
|
||||
</th>
|
||||
<th class="col-sm-1" data-visible="true" data-field="assets_count" data-sortable="true">
|
||||
<i class="fas fa-barcode" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.asset_count') }}</span>
|
||||
</th>
|
||||
<th class="col-sm-1" data-visible="true" data-field="accessories_count" data-sortable="true">
|
||||
<i class="far fa-keyboard" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.accessories_count') }}</span>
|
||||
</th>
|
||||
<th class="col-sm-1" data-visible="true" data-field="consumables_count" data-sortable="true">
|
||||
<i class="fas fa-tint" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.consumables_count') }}</span>
|
||||
</th>
|
||||
<th class="col-sm-1" data-visible="true" data-field="components_count" data-sortable="true">
|
||||
<i class="far fa-hdd" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.components_count') }}</span>
|
||||
</th>
|
||||
<th class="col-sm-1" data-visible="true" data-field="licenses_count" data-sortable="true">
|
||||
<i class="far fa-save" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.licenses_count') }}</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div> <!-- /.col -->
|
||||
<div class="text-center col-md-12" style="padding-top: 10px;">
|
||||
<a href="{{ route('companies.index') }}" class="btn btn-primary btn-sm" style="width: 100%">{{ trans('general.viewall') }}</a>
|
||||
</div>
|
||||
</div> <!-- /.row -->
|
||||
|
||||
</div><!-- /.box-body -->
|
||||
</div> <!-- /.box -->
|
||||
|
||||
@else
|
||||
<!-- Locations -->
|
||||
<div class="box box-default">
|
||||
<div class="box-header with-border">
|
||||
<h2 class="box-title">{{ trans('general.locations') }}</h2>
|
||||
<div class="box-tools pull-right">
|
||||
<button type="button" class="btn btn-box-tool" data-widget="collapse">
|
||||
<i class="fas fa-minus" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.collapse') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="table-responsive">
|
||||
<table
|
||||
data-cookie-id-table="dashLocationSummary"
|
||||
data-height="400"
|
||||
data-pagination="true"
|
||||
data-side-pagination="server"
|
||||
data-sort-order="desc"
|
||||
data-sort-field="assets_count"
|
||||
id="dashLocationSummary"
|
||||
class="table table-striped snipe-table"
|
||||
data-url="{{ route('api.locations.index', ['sort' => 'assets_count', 'order' => 'asc']) }}">
|
||||
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-sm-3" data-visible="true" data-field="name" data-formatter="locationsLinkFormatter" data-sortable="true">{{ trans('general.name') }}</th>
|
||||
|
||||
<th class="col-sm-1" data-visible="true" data-field="assets_count" data-sortable="true">
|
||||
<i class="fas fa-barcode" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.asset_count') }}</span>
|
||||
</th>
|
||||
<th class="col-sm-1" data-visible="true" data-field="assigned_assets_count" data-sortable="true">
|
||||
|
||||
{{ trans('general.assigned') }}
|
||||
</th>
|
||||
<th class="col-sm-1" data-visible="true" data-field="users_count" data-sortable="true">
|
||||
<i class="fas fa-users" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.people') }}</span>
|
||||
|
||||
</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div> <!-- /.col -->
|
||||
<div class="text-center col-md-12" style="padding-top: 10px;">
|
||||
<a href="{{ route('locations.index') }}" class="btn btn-primary btn-sm" style="width: 100%">{{ trans('general.viewall') }}</a>
|
||||
</div>
|
||||
</div> <!-- /.row -->
|
||||
|
||||
</div><!-- /.box-body -->
|
||||
</div> <!-- /.box -->
|
||||
|
||||
@endif
|
||||
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
</div>
|
||||
<div class="col-md-5">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('null_expected_checkin_date', '1', false, ['checked' => 'false']) }}
|
||||
{{ Form::checkbox('null_expected_checkin_date', '1', false) }}
|
||||
{{ trans_choice('general.set_to_null', count($assets), ['asset_count' => count($assets)]) }}
|
||||
</label>
|
||||
</div>
|
||||
|
@ -92,9 +92,13 @@
|
|||
{{ Form::radio('update_real_loc', '1', old('update_real_loc'), ['checked'=> 'checked', 'aria-label'=>'update_real_loc']) }}
|
||||
{{ trans('admin/hardware/form.asset_location_update_default_current') }}
|
||||
</label>
|
||||
<label class="form-control">
|
||||
{{ Form::radio('update_real_loc', '0', old('update_real_loc'), ['aria-label'=>'update_default_loc']) }}
|
||||
{{ trans('admin/hardware/form.asset_location_update_default') }}
|
||||
</label>
|
||||
<label class="form-control">
|
||||
{{ Form::radio('update_real_loc', '0', old('update_real_loc'), ['aria-label'=>'update_default_loc']) }}
|
||||
{{ trans('admin/hardware/form.asset_location_update_default') }}
|
||||
{{ Form::radio('update_real_loc', '2', old('update_real_loc'), ['aria-label'=>'update_default_loc']) }}
|
||||
{{ trans('admin/hardware/form.asset_location_update_actual') }}
|
||||
</label>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
{{ trans('general.assets') }}
|
||||
|
||||
@if (Request::has('order_number'))
|
||||
: Order #{{ Request::get('order_number') }}
|
||||
: Order #{{ strval(Request::get('order_number')) }}
|
||||
@endif
|
||||
@stop
|
||||
|
||||
|
@ -88,7 +88,7 @@
|
|||
class="table table-striped snipe-table"
|
||||
data-url="{{ route('api.assets.index',
|
||||
array('status' => e(Request::get('status')),
|
||||
'order_number'=>e(Request::get('order_number')),
|
||||
'order_number'=>e(strval(Request::get('order_number'))),
|
||||
'company_id'=>e(Request::get('company_id')),
|
||||
'status_id'=>e(Request::get('status_id')))) }}"
|
||||
data-export-options='{
|
||||
|
|
|
@ -631,7 +631,7 @@
|
|||
</div>
|
||||
@endif
|
||||
|
||||
@if (($asset->model) && ($asset->model->eol))
|
||||
@if (($asset->asset_eol_date) && ($asset->purchase_date))
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<strong>
|
||||
|
@ -639,7 +639,7 @@
|
|||
</strong>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
{{ $asset->model->eol }}
|
||||
{{ Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date) }}
|
||||
{{ trans('admin/hardware/form.months') }}
|
||||
|
||||
</div>
|
||||
|
@ -650,6 +650,9 @@
|
|||
<div class="col-md-2">
|
||||
<strong>
|
||||
{{ trans('admin/hardware/form.eol_date') }}
|
||||
@if ($asset->purchase_date)
|
||||
{!! $asset->asset_eol_date < date("Y-m-d") ? '<i class="fas fa-exclamation-triangle text-orange" aria-hidden="true"></i>' : '' !!}
|
||||
@endif
|
||||
</strong>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{ ($snipeSettings) && ($snipeSettings->site_name) ? $snipeSettings->site_name : 'Snipe-IT' }}</title>
|
||||
|
||||
<link rel="shortcut icon" type="image/ico" href="{{ ($snipeSettings) && ($snipeSettings->favicon!='') ? Storage::disk('public')->url('').e($snipeSettings->favicon) : 'favicon.ico' }} ">
|
||||
<link rel="shortcut icon" type="image/ico" href="{{ ($snipeSettings) && ($snipeSettings->favicon!='') ? Storage::disk('public')->url(e($snipeSettings->favicon)) : config('app.url').'/favicon.ico' }}">
|
||||
{{-- stylesheets --}}
|
||||
<link rel="stylesheet" href="{{ url(mix('css/dist/all.css')) }}">
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
|
||||
<div class="input-group col-md-4">
|
||||
<div class="input-group date" data-provide="datepicker" data-date-format="yyyy-mm-dd" data-autoclose="true" data-date-clear-btn="true">
|
||||
<input type="text" class="form-control" placeholder="{{ trans('general.select_date') }}" name="expiration_date" id="expiration_date" value="{{ old('expiration_date', $item->expiration_date) }}" maxlength="10">
|
||||
<input type="text" class="form-control" placeholder="{{ trans('general.select_date') }}" name="expiration_date" id="expiration_date" value="{{ old('expiration_date', ($item->expiration_date) ? $item->expiration_date->format('Y-m-d') : '') }}" maxlength="10">
|
||||
<span class="input-group-addon"><i class="fas fa-calendar" aria-hidden="true"></i></span>
|
||||
</div>
|
||||
{!! $errors->first('expiration_date', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
|
@ -93,7 +93,7 @@
|
|||
|
||||
<div class="input-group col-md-4">
|
||||
<div class="input-group date" data-provide="datepicker" data-date-format="yyyy-mm-dd" data-autoclose="true" data-date-clear-btn="true">
|
||||
<input type="text" class="form-control" placeholder="{{ trans('general.select_date') }}" name="termination_date" id="termination_date" value="{{ old('termination_date', $item->termination_date) }}" maxlength="10">
|
||||
<input type="text" class="form-control" placeholder="{{ trans('general.select_date') }}" name="termination_date" id="termination_date" value="{{ old('termination_date', ($item->termination_date) ? $item->termination_date->format('Y-m-d') : '') }}" maxlength="10">
|
||||
<span class="input-group-addon"><i class="fas fa-calendar" aria-hidden="true"></i></span>
|
||||
</div>
|
||||
{!! $errors->first('termination_date', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
|
|
|
@ -235,9 +235,16 @@
|
|||
])
|
||||
}}
|
||||
</div>
|
||||
@if ($activeFile->first_row)
|
||||
<div class="col-md-5">
|
||||
<p class="form-control-static">{{ str_limit($activeFile->first_row[$index], 50, '...') }}</p>
|
||||
</div>
|
||||
@else
|
||||
@php
|
||||
$statusText = trans('help.empty_file');
|
||||
$statusType = 'info';
|
||||
@endphp
|
||||
@endif
|
||||
</div><!-- /div row -->
|
||||
@endforeach
|
||||
@else
|
||||
|
|
|
@ -104,6 +104,17 @@
|
|||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#history" data-toggle="tab">
|
||||
<span class="hidden-lg hidden-md">
|
||||
<i class="fas fa-hdd fa-2x" aria-hidden="true"></i>
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('general.history') }}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
@ -319,6 +330,51 @@
|
|||
</div><!-- /.table-responsive -->
|
||||
</div><!-- /.tab-pane -->
|
||||
|
||||
<div class="tab-pane" id="history">
|
||||
<h2 class="box-title">{{ trans('general.history') }}</h2>
|
||||
<!-- checked out assets table -->
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<table
|
||||
class="table table-striped snipe-table"
|
||||
id="assetHistory"
|
||||
data-pagination="true"
|
||||
data-id-table="assetHistory"
|
||||
data-search="true"
|
||||
data-side-pagination="server"
|
||||
data-show-columns="true"
|
||||
data-show-fullscreen="true"
|
||||
data-show-refresh="true"
|
||||
data-sort-order="desc"
|
||||
data-sort-name="created_at"
|
||||
data-show-export="true"
|
||||
data-export-options='{
|
||||
"fileName": "export-location-asset-{{ $location->id }}-history",
|
||||
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
|
||||
}'
|
||||
|
||||
data-url="{{ route('api.activity.index', ['target_id' => $location->id, 'target_type' => 'location']) }}"
|
||||
data-cookie-id-table="assetHistory"
|
||||
data-cookie="true">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-visible="true" data-field="icon" style="width: 40px;" class="hidden-xs" data-formatter="iconFormatter">{{ trans('admin/hardware/table.icon') }}</th>
|
||||
<th class="col-sm-2" data-visible="true" data-field="action_date" data-formatter="dateDisplayFormatter">{{ trans('general.date') }}</th>
|
||||
<th class="col-sm-1" data-visible="true" data-field="admin" data-formatter="usersLinkObjFormatter">{{ trans('general.admin') }}</th>
|
||||
<th class="col-sm-1" data-visible="true" data-field="action_type">{{ trans('general.action') }}</th>
|
||||
<th class="col-sm-2" data-visible="true" data-field="item" data-formatter="polymorphicItemFormatter">{{ trans('general.item') }}</th>
|
||||
<th class="col-sm-2" data-visible="true" data-field="target" data-formatter="polymorphicItemFormatter">{{ trans('general.target') }}</th>
|
||||
<th class="col-sm-2" data-field="note">{{ trans('general.notes') }}</th>
|
||||
<th class="col-md-3" data-field="signature_file" data-visible="false" data-formatter="imageFormatter">{{ trans('general.signature') }}</th>
|
||||
<th class="col-md-3" data-visible="false" data-field="file" data-visible="false" data-formatter="fileUploadFormatter">{{ trans('general.download') }}</th>
|
||||
<th class="col-sm-2" data-field="log_meta" data-visible="true" data-formatter="changeLogFormatter">{{ trans('admin/hardware/table.changed')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div> <!-- /.row -->
|
||||
</div> <!-- /.tab-pane history -->
|
||||
|
||||
</div><!--/.col-md-9-->
|
||||
</div><!--/.col-md-9-->
|
||||
</div><!--/.col-md-9-->
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
data-sort-order="asc"
|
||||
id="manufacturersTable"
|
||||
class="table table-striped snipe-table"
|
||||
data-url="{{route('api.manufacturers.index', ['deleted' => e(Request::get('deleted')) ]) }}"
|
||||
data-url="{{route('api.manufacturers.index', ['deleted' => (request('deleted')=='true') ? 'true' : 'false' ]) }}"
|
||||
data-export-options='{
|
||||
"fileName": "export-manufacturers-{{ date('Y-m-d') }}",
|
||||
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
|
||||
|
|
|
@ -37,21 +37,20 @@
|
|||
@elseif ($field->element=='checkbox')
|
||||
<!-- Checkboxes -->
|
||||
@foreach ($field->formatFieldValuesAsArray() as $key => $value)
|
||||
<div>
|
||||
<label>
|
||||
<input type="checkbox" value="{{ $value }}" name="{{ $field->db_column_name() }}[]" class="minimal" {{ isset($item) ? (in_array($value, array_map('trim', explode(',', $item->{$field->db_column_name()}))) ? ' checked="checked"' : '') : (Request::old($field->db_column_name()) != '' ? ' checked="checked"' : (in_array($key, array_map('trim', explode(',', $field->defaultValue($model->id)))) ? ' checked="checked"' : '')) }}>
|
||||
{{ $value }}
|
||||
</label>
|
||||
</div>
|
||||
<label class="form-control">
|
||||
<input type="checkbox" value="{{ $value }}" name="{{ $field->db_column_name() }}[]" {{ isset($item) ? (in_array($value, array_map('trim', explode(',', $item->{$field->db_column_name()}))) ? ' checked="checked"' : '') : (Request::old($field->db_column_name()) != '' ? ' checked="checked"' : (in_array($key, array_map('trim', explode(',', $field->defaultValue($model->id)))) ? ' checked="checked"' : '')) }}>
|
||||
{{ $value }}
|
||||
</label>
|
||||
|
||||
@endforeach
|
||||
@elseif ($field->element=='radio')
|
||||
@foreach ($field->formatFieldValuesAsArray() as $value)
|
||||
<div>
|
||||
<label>
|
||||
<input type="radio" value="{{ $value }}" name="{{ $field->db_column_name() }}" class="minimal" {{ isset($item) ? ($item->{$field->db_column_name()} == $value ? ' checked="checked"' : '') : (Request::old($field->db_column_name()) != '' ? ' checked="checked"' : (in_array($value, explode(', ', $field->defaultValue($model->id))) ? ' checked="checked"' : '')) }}>
|
||||
|
||||
<label class="form-control">
|
||||
<input type="radio" value="{{ $value }}" name="{{ $field->db_column_name() }}" {{ isset($item) ? ($item->{$field->db_column_name()} == $value ? ' checked="checked"' : '') : (Request::old($field->db_column_name()) != '' ? ' checked="checked"' : (in_array($value, explode(', ', $field->defaultValue($model->id))) ? ' checked="checked"' : '')) }}>
|
||||
{{ $value }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@endforeach
|
||||
|
||||
@endif
|
||||
|
|
|
@ -236,6 +236,12 @@
|
|||
</li>
|
||||
@endif
|
||||
|
||||
@if ($model->min_amt)
|
||||
<li>{{ trans('general.min_amt') }}:
|
||||
{{$model->min_amt }}
|
||||
</li>
|
||||
@endif
|
||||
|
||||
@if ($model->manufacturer)
|
||||
<li>
|
||||
{{ trans('general.manufacturer') }}:
|
||||
|
|
|
@ -35,13 +35,25 @@
|
|||
@endif
|
||||
|
||||
|
||||
@if ($message = Session::get('success-unescaped'))
|
||||
<div class="col-md-12">
|
||||
<div class="alert alert-success fade in">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
<i class="fas fa-check faa-pulse animated"></i>
|
||||
<strong>{{ trans('general.notification_success') }}: </strong>
|
||||
{!! $message !!}
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
@if ($assets = Session::get('assets'))
|
||||
@foreach ($assets as $asset)
|
||||
<div class="col-md-12">
|
||||
<div class="alert alert-info fade in">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
<i class="fas fa-info-circle faa-pulse animated"></i>
|
||||
<strong>{{ trans('general.asset_information') }} </strong>
|
||||
<strong>{{ trans('general.asset_information') }}:</strong>
|
||||
<ul>
|
||||
@isset ($asset->model->name)
|
||||
<li><b>{{ trans('general.model_name') }} </b> {{ $asset->model->name }}</li>
|
||||
|
@ -67,7 +79,7 @@
|
|||
<div class="alert alert-info fade in">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
<i class="fas fa-info-circle faa-pulse animated"></i>
|
||||
<strong>{{ trans('general.consumable_information') }}</strong>
|
||||
<strong>{{ trans('general.consumable_information') }}: </strong>
|
||||
<ul><li><b>{{ trans('general.consumable_name') }}</b> {{ $consumable->name }}</li></ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -81,7 +93,7 @@
|
|||
<div class="alert alert-info fade in">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
<i class="fas fa-info-circle faa-pulse animated"></i>
|
||||
<strong>{{ trans('general.accessory_information') }} </strong>
|
||||
<strong>{{ trans('general.accessory_information') }}:</strong>
|
||||
<ul><li><b>{{ trans('general.accessory_name') }}</b> {{ $accessory->name }}</li></ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -94,7 +106,7 @@
|
|||
<div class="alert alert alert-danger fade in">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
<i class="fas fa-exclamation-triangle faa-pulse animated"></i>
|
||||
<strong>{{ trans('general.error') }} </strong>
|
||||
<strong>{{ trans('general.error') }}: </strong>
|
||||
{{ $message }}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -107,7 +119,7 @@
|
|||
<div class="alert alert alert-danger fade in">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
<i class="fas fa-exclamation-triangle faa-pulse animated"></i>
|
||||
<strong>{{ trans('general.notification_error') }} </strong>
|
||||
<strong>{{ trans('general.notification_error') }}: </strong>
|
||||
{{ $message }}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -115,17 +127,19 @@
|
|||
@endif
|
||||
|
||||
|
||||
@if ($messages = Session::get('bulk_errors'))
|
||||
@if ($messages = Session::get('bulk_asset_errors'))
|
||||
<div class="col-md-12">
|
||||
<div class="alert alert alert-danger fade in">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
<i class="fas fa-exclamation-triangle faa-pulse animated"></i>
|
||||
<strong>{{ trans('general.notification_error') }}: </strong>
|
||||
{{ trans('general.notification_bulk_error_hint') }}
|
||||
@foreach($messages as $message)
|
||||
@foreach($messages as $key => $message)
|
||||
@for ($x = 0; $x < count($message); $x++)
|
||||
<ul>
|
||||
<li>{{ $message }}</li>
|
||||
</ul>
|
||||
<li>{{ $message[$x] }}</li>
|
||||
</ul>
|
||||
@endfor
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -530,15 +530,37 @@
|
|||
|
||||
|
||||
function changeLogFormatter(value) {
|
||||
|
||||
var result = '';
|
||||
var pretty_index = '';
|
||||
|
||||
for (var index in value) {
|
||||
result += index + ': <del>' + value[index].old + '</del> <i class="fas fa-long-arrow-alt-right" aria-hidden="true"></i> ' + value[index].new + '<br>'
|
||||
|
||||
|
||||
// Check if it's a custom field
|
||||
if (index.startsWith('_snipeit_')) {
|
||||
pretty_index = index.replace("_snipeit_", "Custom:_");
|
||||
} else {
|
||||
pretty_index = index;
|
||||
}
|
||||
|
||||
extra_pretty_index = prettyLog(pretty_index);
|
||||
|
||||
result += extra_pretty_index + ': <del>' + value[index].old + '</del> <i class="fas fa-long-arrow-alt-right" aria-hidden="true"></i> ' + value[index].new + '<br>'
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
function prettyLog(str) {
|
||||
let frags = str.split('_');
|
||||
for (let i = 0; i < frags.length; i++) {
|
||||
frags[i] = frags[i].charAt(0).toUpperCase() + frags[i].slice(1);
|
||||
}
|
||||
return frags.join(' ');
|
||||
}
|
||||
|
||||
|
||||
// Create a linked phone number in the table list
|
||||
function phoneFormatter(value) {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<!-- Purchase Date -->
|
||||
<!-- EOL Date -->
|
||||
<div class="form-group {{ $errors->has('asset_eol_date') ? ' has-error' : '' }}">
|
||||
<label for="asset_eol_date" class="col-md-3 control-label">{{ trans('admin/hardware/form.eol_date') }}</label>
|
||||
<div class="input-group col-md-4">
|
||||
<div class="input-group date" data-provide="datepicker" data-date-clear-btn="true" data-date-format="yyyy-mm-dd" data-autoclose="true">
|
||||
<input type="text" class="form-control" placeholder="{{ trans('general.select_date') }}" name="asset_eol_date" id="asset_eol_date" readonly value="{{ old('asset_eol_date', optional($item->asset_eol_date)->format('Y-m-d') ?? $item->present()->eol_date() ?? '') }}" style="background-color:inherit">
|
||||
<input type="text" class="form-control" placeholder="{{ trans('general.select_date') }}" name="asset_eol_date" id="asset_eol_date" readonly value="{{ old('asset_eol_date', optional($item->asset_eol_date)->format('Y-m-d') ?? $item->asset_eol_date ?? '') }}" style="background-color:inherit" />
|
||||
<span class="input-group-addon"><i class="fas fa-calendar" aria-hidden="true"></i></span>
|
||||
</div>
|
||||
{!! $errors->first('asset_eol_date', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
|
|
|
@ -304,7 +304,54 @@
|
|||
<label style="grid-area: label-title">Label</label>
|
||||
<input style="grid-area: label-field" x-model="option.label" />
|
||||
<label style="grid-area: source-title">DataSource</label>
|
||||
<input style="grid-area: source-field" x-model="option.datasource" />
|
||||
<select style="grid-area: source-field" x-model="option.datasource">
|
||||
<optgroup label="Asset">
|
||||
<option value="asset_tag">Asset Tag</option>
|
||||
<option value="name">Asset Name</option>
|
||||
<option value="serial">Asset Serial</option>
|
||||
<option value="asset_eol_date">Asset EOL Date</option>
|
||||
<option value="order_number">Asset Order Number</option>
|
||||
<option value="purchase_date">Asset Purchase Date</option>
|
||||
<option value="assignedTo">Assigned To</option>
|
||||
</optgroup>
|
||||
<optgroup label="Asset Model">
|
||||
<option value="model.name">Asset Model Name</option>
|
||||
<option value="model.model_number">Asset Model Number</option>
|
||||
</optgroup>
|
||||
<optgroup label="Manufacturer">
|
||||
<option value="model.manufacturer.name">Manufacturer Name</option>
|
||||
<option value="model.manufacturer.support_email">Manufacturer Support Email</option>
|
||||
<option value="model.manufacturer.support_phone">Manufacturer Support Phone</option>
|
||||
<option value="model.manufacturer.support_url">Manufacturer Support URL</option>
|
||||
</optgroup>
|
||||
<optgroup label="Category">
|
||||
<option value="model.category.name">Category Name</option>
|
||||
</optgroup>
|
||||
<optgroup label="Status">
|
||||
<option value="assetstatus.name">Status</option>
|
||||
</optgroup>
|
||||
<optgroup label="Supplier">
|
||||
<option value="supplier.name">Supplier Name</option>
|
||||
</optgroup>
|
||||
<optgroup label="Default Location">
|
||||
<option value="defaultLoc.name">Default Location Name</option>
|
||||
<option value="defaultLoc.phone">Default Location Phone</option>
|
||||
</optgroup>
|
||||
<optgroup label="Location">
|
||||
<option value="location.name">Location Name</option>
|
||||
<option value="location.phone">Location Phone</option>
|
||||
</optgroup>
|
||||
<optgroup label="Company">
|
||||
<option value="company.email">Company Email</option>
|
||||
<option value="company.name">Company Name</option>
|
||||
<option value="company.phone">Company Phone</option>
|
||||
</optgroup>
|
||||
<optgroup label="Custom Fields">
|
||||
@foreach($customFields as $customField)
|
||||
<option value="{{ $customField->db_column }}">{{ $customField->name }}</option>
|
||||
@endforeach
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
@ -331,4 +378,4 @@
|
|||
><i class="fa-solid fa-trash"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -221,6 +221,38 @@
|
|||
{{ trans('admin/users/table.title') }}
|
||||
</label>
|
||||
|
||||
<!-- new -->
|
||||
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('phone', '1', '1') }}
|
||||
{{ trans('admin/users/table.phone') }}
|
||||
</label>
|
||||
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('user_address', '1', '1') }}
|
||||
{{ trans('general.address') }}
|
||||
</label>
|
||||
|
||||
<label class="form-control">
|
||||
{{Form::checkbox('user_city', '1', '1')}}
|
||||
{{ trans('general.city') }}
|
||||
</label>
|
||||
|
||||
<label class="form-control">
|
||||
{{Form::checkbox('user_state', '1', '1')}}
|
||||
{{ trans('general.state') }}
|
||||
</label>
|
||||
|
||||
<label class="form-control">
|
||||
{{Form::checkbox('user_country', '1', '1')}}
|
||||
{{ trans('general.country') }}
|
||||
</label>
|
||||
|
||||
<label class="form-control">
|
||||
{{Form::checkbox('user_zip', '1', '1')}}
|
||||
{{ trans('general.zip') }}
|
||||
</label>
|
||||
|
||||
|
||||
|
||||
@if ($customfields->count() > 0)
|
||||
|
@ -259,79 +291,131 @@
|
|||
<!-- Order Number -->
|
||||
<div class="form-group">
|
||||
<label for="by_order_number" class="col-md-3 control-label">{{ trans('general.order_number') }}</label>
|
||||
<div class="col-md-5 col-sm-8">
|
||||
<div class="col-md-7">
|
||||
<input class="form-control" type="text" name="by_order_number" value="" aria-label="by_order_number">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Purchase Date -->
|
||||
<div class="form-group purchase-range">
|
||||
<div class="form-group purchase-range{{ ($errors->has('purchase_start') || $errors->has('purchase_end')) ? ' has-error' : '' }}">
|
||||
<label for="purchase_start" class="col-md-3 control-label">{{ trans('general.purchase_date') }} {{ trans('general.range') }}</label>
|
||||
<div class="input-daterange input-group col-md-6" id="datepicker">
|
||||
<input type="text" class="form-control" name="purchase_start" aria-label="purchase_start">
|
||||
<div class="input-daterange input-group col-md-7" id="datepicker">
|
||||
<input type="text" class="form-control" name="purchase_start" aria-label="purchase_start" value="{{ old('purchase_start') }}">
|
||||
<span class="input-group-addon">to</span>
|
||||
<input type="text" class="form-control" name="purchase_end" aria-label="purchase_end">
|
||||
<input type="text" class="form-control" name="purchase_end" aria-label="purchase_end" value="{{ old('purchase_end') }}">
|
||||
</div>
|
||||
|
||||
@if ($errors->has('purchase_start') || $errors->has('purchase_end'))
|
||||
<div class="col-md-9 col-lg-offset-3">
|
||||
{!! $errors->first('purchase_start', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
{!! $errors->first('purchase_end', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Created Date -->
|
||||
<div class="form-group purchase-range">
|
||||
<div class="form-group purchase-range{{ ($errors->has('created_start') || $errors->has('created_end')) ? ' has-error' : '' }}">
|
||||
<label for="created_start" class="col-md-3 control-label">{{ trans('general.created_at') }} {{ trans('general.range') }}</label>
|
||||
<div class="input-daterange input-group col-md-6" id="datepicker">
|
||||
<input type="text" class="form-control" name="created_start" aria-label="created_start">
|
||||
<div class="input-daterange input-group col-md-7" id="datepicker">
|
||||
<input type="text" class="form-control" name="created_start" aria-label="created_start" value="{{ old('created_start') }}">
|
||||
<span class="input-group-addon">to</span>
|
||||
<input type="text" class="form-control" name="created_end" aria-label="created_end">
|
||||
<input type="text" class="form-control" name="created_end" aria-label="created_end" value="{{ old('created_end') }}">
|
||||
</div>
|
||||
|
||||
@if ($errors->has('created_start') || $errors->has('created_end'))
|
||||
<div class="col-md-9 col-lg-offset-3">
|
||||
{!! $errors->first('created_start', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
{!! $errors->first('created_end', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<!-- Checkout Date -->
|
||||
<div class="form-group checkout-range">
|
||||
<div class="form-group checkout-range{{ ($errors->has('checkout_date_start') || $errors->has('checkout_date_end')) ? ' has-error' : '' }}">
|
||||
<label for="checkout_date" class="col-md-3 control-label">{{ trans('general.checkout') }} {{ trans('general.range') }}</label>
|
||||
<div class="input-daterange input-group col-md-6" id="datepicker">
|
||||
<input type="text" class="form-control" name="checkout_date_start" aria-label="checkout_date_start">
|
||||
<div class="input-daterange input-group col-md-7" id="datepicker">
|
||||
<input type="text" class="form-control" name="checkout_date_start" aria-label="checkout_date_start" value="{{ old('checkout_date_start') }}">
|
||||
<span class="input-group-addon">to</span>
|
||||
<input type="text" class="form-control" name="checkout_date_end" aria-label="checkout_date_end">
|
||||
<input type="text" class="form-control" name="checkout_date_end" aria-label="checkout_date_end" value="{{ old('checkout_date_end') }}">
|
||||
</div>
|
||||
|
||||
@if ($errors->has('checkout_date_start') || $errors->has('checkout_date_end'))
|
||||
<div class="col-md-9 col-lg-offset-3">
|
||||
{!! $errors->first('checkout_date_start', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
{!! $errors->first('checkout_date_end', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Last Checkin Date -->
|
||||
<div class="form-group checkin-range">
|
||||
<div class="form-group checkin-range{{ ($errors->has('checkin_date_start') || $errors->has('checkin_date_end')) ? ' has-error' : '' }}">
|
||||
<label for="checkin_date" class="col-md-3 control-label">{{ trans('admin/hardware/table.last_checkin_date') }}</label>
|
||||
<div class="input-daterange input-group col-md-6" id="datepicker">
|
||||
<input type="text" class="form-control" name="checkin_date_start" aria-label="checkin_date_start">
|
||||
<div class="input-daterange input-group col-md-7" id="datepicker">
|
||||
<input type="text" class="form-control" name="checkin_date_start" aria-label="checkin_date_start" value="{{ old('checkin_date_start') }}">
|
||||
<span class="input-group-addon">{{ strtolower(trans('general.to')) }}</span>
|
||||
<input type="text" class="form-control" name="checkin_date_end" aria-label="checkin_date_end">
|
||||
<input type="text" class="form-control" name="checkin_date_end" aria-label="checkin_date_end" value="{{ old('checkin_date_end') }}">
|
||||
</div>
|
||||
|
||||
@if ($errors->has('checkin_date_start') || $errors->has('checkin_date_end'))
|
||||
<div class="col-md-9 col-lg-offset-3">
|
||||
{!! $errors->first('checkin_date_start', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
{!! $errors->first('checkin_date_end', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<!-- Expected Checkin Date -->
|
||||
<div class="form-group expected_checkin-range">
|
||||
<div class="form-group expected_checkin-range{{ ($errors->has('expected_checkin_start') || $errors->has('expected_checkin_end')) ? ' has-error' : '' }}">
|
||||
<label for="expected_checkin_start" class="col-md-3 control-label">{{ trans('admin/hardware/form.expected_checkin') }}</label>
|
||||
<div class="input-daterange input-group col-md-6" id="datepicker">
|
||||
<input type="text" class="form-control" name="expected_checkin_start" aria-label="expected_checkin_start">
|
||||
<div class="input-daterange input-group col-md-7" id="datepicker">
|
||||
<input type="text" class="form-control" name="expected_checkin_start" aria-label="expected_checkin_start" value="{{ old('expected_checkin_start') }}">
|
||||
<span class="input-group-addon">to</span>
|
||||
<input type="text" class="form-control" name="expected_checkin_end" aria-label="expected_checkin_end">
|
||||
<input type="text" class="form-control" name="expected_checkin_end" aria-label="expected_checkin_end" value="{{ old('expected_checkin_end') }}">
|
||||
</div>
|
||||
|
||||
@if ($errors->has('expected_checkin_start') || $errors->has('expected_checkin_end'))
|
||||
<div class="col-md-9 col-lg-offset-3">
|
||||
{!! $errors->first('expected_checkin_start', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
{!! $errors->first('expected_checkin_end', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Last Audit Date -->
|
||||
<div class="form-group last_audit-range">
|
||||
<div class="form-group last_audit-range{{ ($errors->has('last_audit_start') || $errors->has('last_audit_end')) ? ' has-error' : '' }}">
|
||||
<label for="last_audit_start" class="col-md-3 control-label">{{ trans('general.last_audit') }}</label>
|
||||
<div class="input-daterange input-group col-md-6" id="datepicker">
|
||||
<input type="text" class="form-control" name="last_audit_start" aria-label="last_audit_start">
|
||||
<div class="input-daterange input-group col-md-7" id="datepicker">
|
||||
<input type="text" class="form-control" name="last_audit_start" aria-label="last_audit_start" value="{{ old('last_audit_start') }}">
|
||||
<span class="input-group-addon">to</span>
|
||||
<input type="text" class="form-control" name="last_audit_end" aria-label="last_audit_end">
|
||||
<input type="text" class="form-control" name="last_audit_end" aria-label="last_audit_end" value="{{ old('last_audit_end') }}">
|
||||
</div>
|
||||
|
||||
@if ($errors->has('last_audit_start') || $errors->has('last_audit_end'))
|
||||
<div class="col-md-9 col-lg-offset-3">
|
||||
{!! $errors->first('last_audit_start', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
{!! $errors->first('last_audit_end', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<!-- Next Audit Date -->
|
||||
<div class="form-group next_audit-range">
|
||||
<div class="form-group next_audit-range{{ ($errors->has('next_audit_start') || $errors->has('next_audit_end')) ? ' has-error' : '' }}">
|
||||
<label for="next_audit_start" class="col-md-3 control-label">{{ trans('general.next_audit_date') }}</label>
|
||||
<div class="input-daterange input-group col-md-6" id="datepicker">
|
||||
<input type="text" class="form-control" name="next_audit_start" aria-label="nex_audit_start">
|
||||
<div class="input-daterange input-group col-md-7" id="datepicker">
|
||||
<input type="text" class="form-control" name="next_audit_start" aria-label="next_audit_start" value="{{ old('next_audit_start') }}">
|
||||
<span class="input-group-addon">to</span>
|
||||
<input type="text" class="form-control" name="next_audit_end" aria-label="next_audit_end">
|
||||
<input type="text" class="form-control" name="next_audit_end" aria-label="next_audit_end" value="{{ old('next_audit_end') }}">
|
||||
</div>
|
||||
|
||||
@if ($errors->has('next_audit_start') || $errors->has('next_audit_end'))
|
||||
<div class="col-md-9 col-lg-offset-3">
|
||||
{!! $errors->first('next_audit_start', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
{!! $errors->first('next_audit_end', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
|
|
|
@ -137,7 +137,7 @@
|
|||
@csrf
|
||||
|
||||
|
||||
<div class="form-group {{ $errors->has((isset($fieldname) ? $fieldname : 'image')) ? 'has-error' : '' }}" style="margin-bottom: 0px;">
|
||||
<div class="form-group {{ $errors->has((isset($fieldname) ? $fieldname : 'file')) ? 'has-error' : '' }}" style="margin-bottom: 0px;">
|
||||
<div class="col-md-8 col-xs-8">
|
||||
|
||||
|
||||
|
@ -145,26 +145,18 @@
|
|||
<label class="btn btn-default col-md-12 col-xs-12" aria-hidden="true">
|
||||
<i class="fas fa-paperclip" aria-hidden="true"></i>
|
||||
{{ trans('button.select_file') }}
|
||||
|
||||
<input type="file" name="file" class="js-uploadFile" id="uploadFile" data-maxsize="{{ Helper::file_upload_max_size() }}" accept="application/zip" style="display:none;" aria-label="file" aria-hidden="true">
|
||||
|
||||
|
||||
</label>
|
||||
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-md-4 col-xs-4">
|
||||
<button class="btn btn-primary col-md-12 col-xs-12" id="uploadButton" disabled>{{ trans('button.upload') }} <span id="uploadIcon"></span></button>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-md-12">
|
||||
|
||||
<p class="label label-default col-md-12" style="font-size: 120%!important; margin-top: 10px; margin-bottom: 10px;" id="uploadFile-info"></p>
|
||||
|
||||
<p class="help-block" style="margin-top: 10px;" id="uploadFile-status">{{ trans_choice('general.filetypes_accepted_help', 1, ['size' => Helper::file_upload_max_size_readable(), 'types' => '.zip']) }}</p>
|
||||
{!! $errors->first('image', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
|
||||
|
||||
{!! $errors->first('file', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -216,7 +216,7 @@
|
|||
{{ Form::label('label2_fields', trans('admin/settings/general.label2_fields')) }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
@include('partials.label2-field-definitions', [ 'name' => 'label2_fields', 'value' => old('label2_fields', $setting->label2_fields) ])
|
||||
@include('partials.label2-field-definitions', [ 'name' => 'label2_fields', 'value' => old('label2_fields', $setting->label2_fields), 'customFields' => $customFields ])
|
||||
{!! $errors->first('label2_fields', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
<p class="help-block">{{ trans('admin/settings/general.label2_fields_help') }}</p>
|
||||
</div>
|
||||
|
|
|
@ -39,6 +39,16 @@
|
|||
@include ('partials.forms.edit.department-select', ['translated_name' => trans('general.department'), 'fieldname' => 'department_id'])
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<div class=" col-md-9 col-md-offset-3">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('null_department_id', '1', false) }}
|
||||
{{ trans_choice('general.set_users_field_to_null', count($users), ['field' => trans('general.department'), 'user_count' => count($users)]) }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Location -->
|
||||
@include ('partials.forms.edit.location-select', ['translated_name' => trans('general.location'), 'fieldname' => 'location_id'])
|
||||
|
||||
|
@ -55,11 +65,31 @@
|
|||
<!-- Company -->
|
||||
@if (\App\Models\Company::canManageUsersCompanies())
|
||||
@include ('partials.forms.edit.company-select', ['translated_name' => trans('general.select_company'), 'fieldname' => 'company_id'])
|
||||
|
||||
<div class="form-group">
|
||||
<div class=" col-md-9 col-md-offset-3">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('null_company_id', '1', false) }}
|
||||
{{ trans_choice('general.set_users_field_to_null', count($users), ['field' => trans('general.company'), 'user_count' => count($users)]) }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endif
|
||||
|
||||
<!-- Manager -->
|
||||
@include ('partials.forms.edit.user-select', ['translated_name' => trans('admin/users/table.manager'), 'fieldname' => 'manager_id'])
|
||||
|
||||
<div class="form-group">
|
||||
<div class=" col-md-9 col-md-offset-3">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('null_manager_id', '1', false) }}
|
||||
{{ trans_choice('general.set_users_field_to_null', count($users), ['field' => trans('admin/users/table.manager'), 'user_count' => count($users)]) }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- language -->
|
||||
<div class="form-group {{ $errors->has('locale') ? 'has-error' : '' }}">
|
||||
<label class="col-md-3 control-label" for="locale">{{ trans('general.language') }}</label>
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
<th class="col-md-3">{{ trans('general.name') }}</th>
|
||||
<th class="col-md-3">{{ trans('general.email') }}</th>
|
||||
<th class="col-md-3">{{ trans('general.username') }}</th>
|
||||
<th class="col-md-3">{{ trans('general.employee_number') }}</th>
|
||||
<th class="col-md-3">{{ trans('general.groups') }}</th>
|
||||
<th class="col-md-1 text-right">
|
||||
<i class="fas fa-barcode fa-fw" aria-hidden="true" style="font-size: 17px;"></i>
|
||||
|
@ -80,6 +81,9 @@
|
|||
<td>
|
||||
{{ $user->username }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $user->employee_num }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
@foreach ($user->groups as $group)
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
<div class="col-md-12">
|
||||
<!-- Location -->
|
||||
@include ('partials.forms.edit.location-select', ['translated_name' => trans('general.location'), 'fieldname' => 'location_id'])
|
||||
@include ('partials.forms.edit.location-select', ['translated_name' => trans('general.location'), 'fieldname' => 'location_id[]', 'multiple' => true])
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -80,8 +80,8 @@
|
|||
<td>{{ $counter }}</td>
|
||||
<td>{{ $asset->asset_tag }}</td>
|
||||
<td>{{ $asset->name }}</td>
|
||||
<td>{{ $asset->model->category->name }}</td>
|
||||
<td>{{ $asset->model->name }}</td>
|
||||
<td>{{ (($asset->model) && ($asset->model->category)) ? $asset->model->category->name : trans('general.invalid_category') }}</td>
|
||||
<td>{{ ($asset->model) ? $asset->model->name : trans('general.invalid_model') }}</td>
|
||||
<td>{{ $asset->serial }}</td>
|
||||
<td>
|
||||
{{ $asset->last_checkout }}</td>
|
||||
|
|
|
@ -224,6 +224,11 @@ Route::group(['prefix' => 'admin', 'middleware' => ['auth', 'authorize:superuser
|
|||
[SettingsController::class, 'postUploadBackup']
|
||||
)->name('settings.backups.upload');
|
||||
|
||||
// Handle redirect from after POST request from backup restore
|
||||
Route::get('/restore/{filename?}', function () {
|
||||
return redirect(route('settings.backups.index'));
|
||||
});
|
||||
|
||||
Route::get('/', [SettingsController::class, 'getBackups'])->name('settings.backups.index');
|
||||
});
|
||||
|
||||
|
|
|
@ -122,9 +122,10 @@ Route::group(
|
|||
[AssetCheckinController::class, 'store']
|
||||
)->name('hardware.checkin.store');
|
||||
|
||||
Route::get('{assetId}/view',
|
||||
[AssetsController::class, 'show']
|
||||
)->name('hardware.view');
|
||||
// Redirect old legacy /asset_id/view urls to the resource route version
|
||||
Route::get('{assetId}/view', function ($assetId) {
|
||||
return redirect()->route('hardware.show', ['hardware' => $assetId]);
|
||||
});
|
||||
|
||||
Route::get('{assetId}/qr_code',
|
||||
[AssetsController::class, 'getQrCode']
|
||||
|
@ -178,13 +179,17 @@ Route::group(
|
|||
Route::post('bulkcheckout',
|
||||
[BulkAssetsController::class, 'storeCheckout']
|
||||
)->name('hardware.bulkcheckout.store');
|
||||
|
||||
});
|
||||
|
||||
Route::resource('hardware',
|
||||
AssetsController::class,
|
||||
[
|
||||
'middleware' => ['auth'],
|
||||
'parameters' => ['asset' => 'asset_id'
|
||||
'parameters' => ['asset' => 'asset_id',
|
||||
'names' => [
|
||||
'show' => 'view',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
|
|
19
tests/Feature/Api/Assets/AssetStoreTest.php
Normal file
19
tests/Feature/Api/Assets/AssetStoreTest.php
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Assets;
|
||||
|
||||
use App\Models\User;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AssetStoreTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testRequiresPermissionToCreateAsset()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->create())
|
||||
->postJson(route('api.assets.store'))
|
||||
->assertForbidden();
|
||||
}
|
||||
}
|
62
tests/Feature/Checkouts/LicenseCheckoutTest.php
Normal file
62
tests/Feature/Checkouts/LicenseCheckoutTest.php
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Feature\Checkouts;
|
||||
|
||||
use App\Models\Asset;
|
||||
use App\Models\License;
|
||||
use App\Models\LicenseSeat;
|
||||
use App\Models\User;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class LicenseCheckoutTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testNotesAreStoredInActionLogOnCheckoutToAsset()
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$asset = Asset::factory()->create();
|
||||
$licenseSeat = LicenseSeat::factory()->create();
|
||||
|
||||
$this->actingAs($admin)
|
||||
->post("/licenses/{$licenseSeat->license->id}/checkout", [
|
||||
'checkout_to_type' => 'asset',
|
||||
'assigned_to' => null,
|
||||
'asset_id' => $asset->id,
|
||||
'notes' => 'oh hi there',
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('action_logs', [
|
||||
'action_type' => 'checkout',
|
||||
'target_id' => $asset->id,
|
||||
'target_type' => Asset::class,
|
||||
'item_id' => $licenseSeat->license->id,
|
||||
'item_type' => License::class,
|
||||
'note' => 'oh hi there',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testNotesAreStoredInActionLogOnCheckoutToUser()
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$licenseSeat = LicenseSeat::factory()->create();
|
||||
|
||||
$this->actingAs($admin)
|
||||
->post("/licenses/{$licenseSeat->license->id}/checkout", [
|
||||
'checkout_to_type' => 'user',
|
||||
'assigned_to' => $admin->id,
|
||||
'asset_id' => null,
|
||||
'notes' => 'oh hi there',
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('action_logs', [
|
||||
'action_type' => 'checkout',
|
||||
'target_id' => $admin->id,
|
||||
'target_type' => User::class,
|
||||
'item_id' => $licenseSeat->license->id,
|
||||
'item_type' => License::class,
|
||||
'note' => 'oh hi there',
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ use PHPUnit\Framework\Assert;
|
|||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
|
||||
class CustomReportTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
|
19
tests/Unit/Helpers/HelperTest.php
Normal file
19
tests/Unit/Helpers/HelperTest.php
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Unit\Helpers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use Tests\TestCase;
|
||||
|
||||
class HelperTest extends TestCase
|
||||
{
|
||||
public function testDefaultChartColorsMethodHandlesHighValues()
|
||||
{
|
||||
$this->assertIsString(Helper::defaultChartColors(1000));
|
||||
}
|
||||
|
||||
public function testDefaultChartColorsMethodHandlesNegativeNumbers()
|
||||
{
|
||||
$this->assertIsString(Helper::defaultChartColors(-1));
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue