Compare commits
182 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9221641bba | |||
| 6bca1e3b22 | |||
| 00cea3eb3c | |||
| 19b52a2f24 | |||
| 6237f6192c | |||
| cc58d4c3ad | |||
| 060c59bf9d | |||
| 6fd3c494be | |||
| 8adfa8dd83 | |||
| 6c9001df09 | |||
| d6159d8cb5 | |||
| 81b9753b79 | |||
| d8b1eec91b | |||
| b871813cfd | |||
| 6f7dce53cc | |||
| 13d2af2155 | |||
| bf3794822c | |||
| 1fa8fba5fe | |||
| 3d7697da6f | |||
| 42cf17d3bf | |||
| 783e37f06d | |||
| 9a4cda0bf6 | |||
| b6279af1d8 | |||
| bc0a7542ac | |||
| b136e9e29d | |||
| 50c910461a | |||
| 88a84e9350 | |||
| 43bb8ae0a8 | |||
| 638071dadd | |||
| 8a4c90ade8 | |||
| 1dfa1da0ee | |||
| 71ebade641 | |||
| b86b05c4fc | |||
| 35a70988cb | |||
| 56ba26eb45 | |||
| adb8be9345 | |||
| abc9ee22c6 | |||
| e5ee9760c0 | |||
| 7868a8c174 | |||
| 03df4cec45 | |||
| e2c3386c33 | |||
| a866d6b16e | |||
| a76a69d085 | |||
| 280e778749 | |||
| 60ba898167 | |||
| 2c9d5b9ea3 | |||
| eb6e2636b5 | |||
| 4c1964d509 | |||
| 7547277352 | |||
| 3e00bc49fd | |||
| 99e0b65de7 | |||
| f4c1460c2b | |||
| bb2e1de0a8 | |||
| 7154d23759 | |||
| df23fd0dee | |||
| adfb8895df | |||
| c8e12ddb5c | |||
| 5b181ecea7 | |||
| 728aaaab20 | |||
| 095a7d9b34 | |||
| cf53f2778f | |||
| 65e20282b6 | |||
| 405c5b5ad0 | |||
| 6f0fe16b87 | |||
| 111daffc17 | |||
| b8a478f558 | |||
| 9f7084d077 | |||
| 0840cd3df3 | |||
| cefdaf9a9b | |||
| 13335b19e9 | |||
| 6e471a27e7 | |||
| 513ea67e7d | |||
| 3868e711f4 | |||
| f33f712de7 | |||
| c12e1f6d6c | |||
| 479abd5231 | |||
| a60a24a4a8 | |||
| 55b3050ca8 | |||
| 2c996a8508 | |||
| 84f8eee869 | |||
| 590c19dbd7 | |||
| fa47707974 | |||
| ca62481083 | |||
| 1c3306046c | |||
| f4fc845375 | |||
| a7af987322 | |||
| c4eaae923a | |||
| 849ba02516 | |||
| 9dcd14a712 | |||
| 3412b4dc5a | |||
| a3b96aff1f | |||
| 9bb191f29f | |||
| 4a43ccfa92 | |||
| b73e8642d3 | |||
| cfe2277a64 | |||
| e776c2cffa | |||
| ca59bc3c9c | |||
| 575362f4dc | |||
| f0139c5e41 | |||
| 5f8ac66036 | |||
| a49e66c689 | |||
| 1630e4bc2f | |||
| bf674a0f4d | |||
| b170755c3d | |||
| b25612bbac | |||
| a43183ff96 | |||
| 5aa34695a1 | |||
| 3b36372a66 | |||
| e763693829 | |||
| e08d60ed18 | |||
| 9e6e2de71e | |||
| b49935701b | |||
| 76cc5995d9 | |||
| c0fbf106ed | |||
| 7b4020c5e9 | |||
| 383e3829e5 | |||
| 91356af838 | |||
| 4c967a43a7 | |||
| deca842eb0 | |||
| 44366746dd | |||
| 3806cec10e | |||
| a800fa07f9 | |||
| 32c360f032 | |||
| 25f1445afc | |||
| 0042359e5f | |||
| cf2e2bfbc1 | |||
| 60f9a8be9a | |||
| 8316db9702 | |||
| 1a480435de | |||
| ebc373744a | |||
| 650aa25659 | |||
| 212dd06948 | |||
| b6eea2e170 | |||
| 688017bd8a | |||
| 58a9c27342 | |||
| f52b00256d | |||
| 2d48d96b3c | |||
| abd13a1140 | |||
| 5882d71f9b | |||
| dc92bbf61e | |||
| e6fdeb0e8a | |||
| 3b948c7b7e | |||
| d965fe759a | |||
| 5e4a3379a9 | |||
| 9dc428b720 | |||
| 8a5b469ff8 | |||
| ed06f32a7a | |||
| a876703f8f | |||
| 01bb8d8c9a | |||
| f452204d62 | |||
| 0eabb147b2 | |||
| 2e0e39ccc8 | |||
| 63e733f0d6 | |||
| 2406d2cfdb | |||
| e074ca0bf9 | |||
| 13c37e708f | |||
| 3f76d65b95 | |||
| 87bce0c097 | |||
| 6d41c8cf67 | |||
| 22385a8e35 | |||
| 77fa213ccd | |||
| d0a82adc3f | |||
| de2aa903c5 | |||
| 42ec2548c9 | |||
| a2cba67f4e | |||
| 7d45cfff2c | |||
| f1ab8253f0 | |||
| e5d3df7d24 | |||
| 987676df08 | |||
| f16f62f76c | |||
| dfa33f651a | |||
| 30c2927987 | |||
| e8159d97fa | |||
| 2deba17d91 | |||
| 3574ef5bb9 | |||
| abf13f1619 | |||
| 4a7df470f0 | |||
| c9101f4d97 | |||
| 6e9a46e582 | |||
| 1d3124f89f | |||
| ada1a593a4 | |||
| d556f0d275 |
@@ -36,7 +36,7 @@ jobs:
|
||||
|
||||
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
|
||||
- name: Run Codacy Analysis CLI
|
||||
uses: codacy/codacy-analysis-cli-action@v4.3.0
|
||||
uses: codacy/codacy-analysis-cli-action@v4.4.0
|
||||
with:
|
||||
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
|
||||
# You can also omit the token and run the tools that support default configurations
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM alpine:3.18.5
|
||||
FROM alpine:3.18.6
|
||||
# Apache + PHP
|
||||
RUN apk add --no-cache \
|
||||
apache2 \
|
||||
|
||||
+15
-2
@@ -45,8 +45,21 @@ DB_PASSWORD={}
|
||||
|
||||
Now you are ready to run the entire test suite from your terminal:
|
||||
|
||||
`php artisan test`
|
||||
```shell
|
||||
php artisan test
|
||||
````
|
||||
|
||||
To run individual test files, you can pass the path to the test that you want to run:
|
||||
|
||||
`php artisan test tests/Unit/AccessoryTest.php`
|
||||
```shell
|
||||
php artisan test tests/Unit/AccessoryTest.php
|
||||
```
|
||||
|
||||
Some tests, like ones concerning LDAP, are marked with the `@group` annotation. Those groups can be run, or excluded, using the `--group` or `--exclude-group` flags:
|
||||
|
||||
```shell
|
||||
php artisan test --group=ldap
|
||||
|
||||
php artisan test --exclude-group=ldap
|
||||
```
|
||||
This can be helpful if a set of tests are failing because you don't have an extension, like LDAP, installed.
|
||||
|
||||
@@ -4,28 +4,27 @@ namespace App\Http\Controllers\Accessories;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\AssetFileRequest;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Accessory;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Accessory\HttpFoundation\JsonResponse;
|
||||
use enshrined\svgSanitize\Sanitizer;
|
||||
|
||||
class AccessoriesFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Validates and stores files associated with a accessory.
|
||||
*
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param AssetFileRequest $request
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $accessoryId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*@author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
*/
|
||||
public function store(AssetFileRequest $request, $accessoryId = null)
|
||||
public function store(UploadFileRequest $request, $accessoryId = null)
|
||||
{
|
||||
|
||||
if (config('app.lock_passwords')) {
|
||||
@@ -45,30 +44,7 @@ class AccessoriesFilesController extends Controller
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$file_name = 'accessory-'.$accessory->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
|
||||
|
||||
|
||||
// Check for SVG and sanitize it
|
||||
if ($extension == 'svg') {
|
||||
\Log::debug('This is an SVG');
|
||||
\Log::debug($file_name);
|
||||
|
||||
$sanitizer = new Sanitizer();
|
||||
$dirtySVG = file_get_contents($file->getRealPath());
|
||||
$cleanSVG = $sanitizer->sanitize($dirtySVG);
|
||||
|
||||
try {
|
||||
Storage::put('private_uploads/accessories/'.$file_name, $cleanSVG);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Upload no workie :( ');
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
} else {
|
||||
Storage::put('private_uploads/accessories/'.$file_name, file_get_contents($file));
|
||||
}
|
||||
|
||||
$file_name = $request->handleFile('private_uploads/accessories/', 'accessory-'.$accessory->id, $file);
|
||||
//Log the upload to the log
|
||||
$accessory->logUpload($file_name, e($request->input('notes')));
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Events\CheckoutableCheckedOut;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Transformers\AccessoriesTransformer;
|
||||
@@ -278,7 +279,7 @@ class AccessoriesController extends Controller
|
||||
public function checkout(Request $request, $accessoryId)
|
||||
{
|
||||
// Check if the accessory exists
|
||||
if (is_null($accessory = Accessory::find($accessoryId))) {
|
||||
if (is_null($accessory = Accessory::withCount('users as users_count')->find($accessoryId))) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.does_not_exist')));
|
||||
}
|
||||
|
||||
@@ -302,7 +303,7 @@ class AccessoriesController extends Controller
|
||||
'note' => $request->get('note'),
|
||||
]);
|
||||
|
||||
$accessory->logCheckout($request->input('note'), $user);
|
||||
event(new CheckoutableCheckedOut($accessory, $user, Auth::user(), $request->input('note')));
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/accessories/message.checkout.success')));
|
||||
}
|
||||
|
||||
@@ -36,7 +36,8 @@ class AssetMaintenancesController extends Controller
|
||||
{
|
||||
$this->authorize('view', Asset::class);
|
||||
|
||||
$maintenances = AssetMaintenance::select('asset_maintenances.*')->with('asset', 'asset.model', 'asset.location', 'asset.defaultLoc', 'supplier', 'asset.company', 'admin');
|
||||
$maintenances = AssetMaintenance::select('asset_maintenances.*')
|
||||
->with('asset', 'asset.model', 'asset.location', 'asset.defaultLoc', 'supplier', 'asset.company', 'asset.assetstatus', 'admin');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$maintenances = $maintenances->TextSearch($request->input('search'));
|
||||
@@ -47,7 +48,7 @@ class AssetMaintenancesController extends Controller
|
||||
}
|
||||
|
||||
if ($request->filled('supplier_id')) {
|
||||
$maintenances->where('supplier_id', '=', $request->input('supplier_id'));
|
||||
$maintenances->where('asset_maintenances.supplier_id', '=', $request->input('supplier_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('asset_maintenance_type')) {
|
||||
@@ -70,10 +71,13 @@ class AssetMaintenancesController extends Controller
|
||||
'notes',
|
||||
'asset_tag',
|
||||
'asset_name',
|
||||
'serial',
|
||||
'user_id',
|
||||
'supplier',
|
||||
'is_warranty',
|
||||
'status_label',
|
||||
];
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
|
||||
|
||||
@@ -90,6 +94,12 @@ class AssetMaintenancesController extends Controller
|
||||
case 'asset_name':
|
||||
$maintenances = $maintenances->OrderByAssetName($order);
|
||||
break;
|
||||
case 'serial':
|
||||
$maintenances = $maintenances->OrderByAssetSerial($order);
|
||||
break;
|
||||
case 'status_label':
|
||||
$maintenances = $maintenances->OrderStatusName($order);
|
||||
break;
|
||||
default:
|
||||
$maintenances = $maintenances->orderBy($sort, $order);
|
||||
break;
|
||||
|
||||
@@ -40,7 +40,9 @@ class CompaniesController extends Controller
|
||||
'components_count',
|
||||
];
|
||||
|
||||
$companies = Company::withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'users as users_count');
|
||||
$companies = Company::withCount(['assets as assets_count' => function ($query) {
|
||||
$query->AssetsForShow();
|
||||
}])->withCount('licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'users as users_count');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$companies->TextSearch($request->input('search'));
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Events\CheckoutableCheckedOut;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Transformers\ConsumablesTransformer;
|
||||
@@ -11,6 +12,7 @@ use App\Models\Consumable;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class ConsumablesController extends Controller
|
||||
{
|
||||
@@ -290,17 +292,9 @@ class ConsumablesController extends Controller
|
||||
]
|
||||
);
|
||||
|
||||
// Log checkout event
|
||||
$logaction = $consumable->logCheckout($request->input('note'), $user);
|
||||
$data['log_id'] = $logaction->id;
|
||||
$data['eula'] = $consumable->getEula();
|
||||
$data['first_name'] = $user->first_name;
|
||||
$data['item_name'] = $consumable->name;
|
||||
$data['checkout_date'] = $logaction->created_at;
|
||||
$data['note'] = $logaction->note;
|
||||
$data['require_acceptance'] = $consumable->requireAcceptance();
|
||||
event(new CheckoutableCheckedOut($consumable, $user, Auth::user(), $request->input('note')));
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/consumables/message.checkout.success')));
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/consumables/message.checkout.success')));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,12 @@ class ReportsController extends Controller
|
||||
|
||||
if (($request->filled('item_type')) && ($request->filled('item_id'))) {
|
||||
$actionlogs = $actionlogs->where('item_id', '=', $request->input('item_id'))
|
||||
->where('item_type', '=', 'App\\Models\\'.ucwords($request->input('item_type')));
|
||||
->where('item_type', '=', 'App\\Models\\'.ucwords($request->input('item_type')))
|
||||
->orWhere(function($query) use ($request)
|
||||
{
|
||||
$query->where('target_id', '=', $request->input('item_id'))
|
||||
->where('target_type', '=', 'App\\Models\\'.ucwords($request->input('item_type')));
|
||||
});
|
||||
}
|
||||
|
||||
if ($request->filled('action_type')) {
|
||||
|
||||
@@ -148,30 +148,20 @@ class AssetMaintenancesController extends Controller
|
||||
*/
|
||||
public function edit($assetMaintenanceId = null)
|
||||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
// Check if the asset maintenance exists
|
||||
$this->authorize('update', Asset::class);
|
||||
// Check if the asset maintenance exists
|
||||
if (is_null($assetMaintenance = AssetMaintenance::find($assetMaintenanceId))) {
|
||||
// Redirect to the improvement management page
|
||||
return redirect()->route('maintenances.index')
|
||||
->with('error', trans('admin/asset_maintenances/message.not_found'));
|
||||
} elseif (! $assetMaintenance->asset) {
|
||||
return redirect()->route('maintenances.index')
|
||||
->with('error', 'The asset associated with this maintenance does not exist.');
|
||||
// Redirect to the asset maintenance management page
|
||||
return redirect()->route('maintenances.index')->with('error', trans('admin/asset_maintenances/message.not_found'));
|
||||
} elseif ((!$assetMaintenance->asset) || ($assetMaintenance->asset->deleted_at!='')) {
|
||||
// Redirect to the asset maintenance management page
|
||||
return redirect()->route('maintenances.index')->with('error', 'asset does not exist');
|
||||
} elseif (! Company::isCurrentUserHasAccess($assetMaintenance->asset)) {
|
||||
return static::getInsufficientPermissionsRedirect();
|
||||
}
|
||||
|
||||
if ($assetMaintenance->completion_date == '0000-00-00') {
|
||||
$assetMaintenance->completion_date = null;
|
||||
}
|
||||
|
||||
if ($assetMaintenance->start_date == '0000-00-00') {
|
||||
$assetMaintenance->start_date = null;
|
||||
}
|
||||
|
||||
if ($assetMaintenance->cost == '0.00') {
|
||||
$assetMaintenance->cost = null;
|
||||
}
|
||||
|
||||
// Prepare Improvement Type List
|
||||
$assetMaintenanceType = [
|
||||
@@ -203,8 +193,10 @@ class AssetMaintenancesController extends Controller
|
||||
// Check if the asset maintenance exists
|
||||
if (is_null($assetMaintenance = AssetMaintenance::find($assetMaintenanceId))) {
|
||||
// Redirect to the asset maintenance management page
|
||||
return redirect()->route('maintenances.index')
|
||||
->with('error', trans('admin/asset_maintenances/message.not_found'));
|
||||
return redirect()->route('maintenances.index')->with('error', trans('admin/asset_maintenances/message.not_found'));
|
||||
} elseif ((!$assetMaintenance->asset) || ($assetMaintenance->asset->deleted_at!='')) {
|
||||
// Redirect to the asset maintenance management page
|
||||
return redirect()->route('maintenances.index')->with('error', 'asset does not exist');
|
||||
} elseif (! Company::isCurrentUserHasAccess($assetMaintenance->asset)) {
|
||||
return static::getInsufficientPermissionsRedirect();
|
||||
}
|
||||
|
||||
@@ -3,26 +3,25 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Requests\AssetFileRequest;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\AssetModel;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use enshrined\svgSanitize\Sanitizer;
|
||||
|
||||
class AssetModelsFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Upload a file to the server.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param AssetFileRequest $request
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $modelId
|
||||
* @return Redirect
|
||||
* @since [v1.0]
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*@since [v1.0]
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*/
|
||||
public function store(AssetFileRequest $request, $modelId = null)
|
||||
public function store(UploadFileRequest $request, $modelId = null)
|
||||
{
|
||||
if (! $model = AssetModel::find($modelId)) {
|
||||
return redirect()->route('models.index')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
@@ -37,27 +36,7 @@ class AssetModelsFilesController extends Controller
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$file_name = 'model-'.$model->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
|
||||
|
||||
// Check for SVG and sanitize it
|
||||
if ($extension=='svg') {
|
||||
\Log::debug('This is an SVG');
|
||||
|
||||
$sanitizer = new Sanitizer();
|
||||
$dirtySVG = file_get_contents($file->getRealPath());
|
||||
$cleanSVG = $sanitizer->sanitize($dirtySVG);
|
||||
|
||||
try {
|
||||
Storage::put('private_uploads/assetmodels/'.$file_name, $cleanSVG);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Upload no workie :( ');
|
||||
\Log::debug($e);
|
||||
}
|
||||
} else {
|
||||
Storage::put('private_uploads/assetmodels/'.$file_name, file_get_contents($file));
|
||||
}
|
||||
|
||||
$file_name = $request->handleFile('private_uploads/assetmodels/','model-'.$model->id,$file);
|
||||
|
||||
$model->logUpload($file_name, e($request->get('notes')));
|
||||
}
|
||||
|
||||
@@ -4,26 +4,25 @@ namespace App\Http\Controllers\Assets;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\AssetFileRequest;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use enshrined\svgSanitize\Sanitizer;
|
||||
|
||||
class AssetFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Upload a file to the server.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param AssetFileRequest $request
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $assetId
|
||||
* @return Redirect
|
||||
* @since [v1.0]
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*@since [v1.0]
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*/
|
||||
public function store(AssetFileRequest $request, $assetId = null)
|
||||
public function store(UploadFileRequest $request, $assetId = null)
|
||||
{
|
||||
if (! $asset = Asset::find($assetId)) {
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
@@ -37,28 +36,7 @@ class AssetFilesController extends Controller
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$file_name = 'hardware-'.$asset->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
|
||||
|
||||
// Check for SVG and sanitize it
|
||||
if ($extension=='svg') {
|
||||
\Log::debug('This is an SVG');
|
||||
|
||||
$sanitizer = new Sanitizer();
|
||||
$dirtySVG = file_get_contents($file->getRealPath());
|
||||
$cleanSVG = $sanitizer->sanitize($dirtySVG);
|
||||
|
||||
try {
|
||||
Storage::put('private_uploads/assets/'.$file_name, $cleanSVG);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Upload no workie :( ');
|
||||
\Log::debug($e);
|
||||
}
|
||||
} else {
|
||||
Storage::put('private_uploads/assets/'.$file_name, file_get_contents($file));
|
||||
}
|
||||
|
||||
$file_name = $request->handleFile('private_uploads/assets/','hardware-'.$asset->id, $file);
|
||||
|
||||
$asset->logUpload($file_name, e($request->get('notes')));
|
||||
}
|
||||
|
||||
@@ -146,7 +146,8 @@ class AssetsController extends Controller
|
||||
$asset->next_audit_date = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
|
||||
}
|
||||
|
||||
if ($asset->assigned_to == '') {
|
||||
// Set location_id to rtd_location_id ONLY if the asset isn't being checked out
|
||||
if (!request('assigned_user') && !request('assigned_asset') && !request('assigned_location')) {
|
||||
$asset->location_id = $request->input('rtd_location_id', null);
|
||||
}
|
||||
|
||||
@@ -521,31 +522,33 @@ class AssetsController extends Controller
|
||||
public function getBarCode($assetId = null)
|
||||
{
|
||||
$settings = Setting::getSettings();
|
||||
$asset = Asset::find($assetId);
|
||||
$barcode_file = public_path().'/uploads/barcodes/'.str_slug($settings->alt_barcode).'-'.str_slug($asset->asset_tag).'.png';
|
||||
if ($asset = Asset::withTrashed()->find($assetId)) {
|
||||
$barcode_file = public_path().'/uploads/barcodes/'.str_slug($settings->alt_barcode).'-'.str_slug($asset->asset_tag).'.png';
|
||||
|
||||
if (isset($asset->id, $asset->asset_tag)) {
|
||||
if (file_exists($barcode_file)) {
|
||||
$header = ['Content-type' => 'image/png'];
|
||||
if (isset($asset->id, $asset->asset_tag)) {
|
||||
if (file_exists($barcode_file)) {
|
||||
$header = ['Content-type' => 'image/png'];
|
||||
|
||||
return response()->file($barcode_file, $header);
|
||||
} else {
|
||||
// Calculate barcode width in pixel based on label width (inch)
|
||||
$barcode_width = ($settings->labels_width - $settings->labels_display_sgutter) * 200.000000000001;
|
||||
return response()->file($barcode_file, $header);
|
||||
} else {
|
||||
// Calculate barcode width in pixel based on label width (inch)
|
||||
$barcode_width = ($settings->labels_width - $settings->labels_display_sgutter) * 200.000000000001;
|
||||
|
||||
$barcode = new \Com\Tecnick\Barcode\Barcode();
|
||||
try {
|
||||
$barcode_obj = $barcode->getBarcodeObj($settings->alt_barcode, $asset->asset_tag, ($barcode_width < 300 ? $barcode_width : 300), 50);
|
||||
file_put_contents($barcode_file, $barcode_obj->getPngData());
|
||||
$barcode = new \Com\Tecnick\Barcode\Barcode();
|
||||
try {
|
||||
$barcode_obj = $barcode->getBarcodeObj($settings->alt_barcode, $asset->asset_tag, ($barcode_width < 300 ? $barcode_width : 300), 50);
|
||||
file_put_contents($barcode_file, $barcode_obj->getPngData());
|
||||
|
||||
return response($barcode_obj->getPngData())->header('Content-type', 'image/png');
|
||||
} catch (\Exception $e) {
|
||||
Log::debug('The barcode format is invalid.');
|
||||
return response($barcode_obj->getPngData())->header('Content-type', 'image/png');
|
||||
} catch (\Exception $e) {
|
||||
Log::debug('The barcode format is invalid.');
|
||||
|
||||
return response(file_get_contents(public_path('uploads/barcodes/invalid_barcode.gif')))->header('Content-type', 'image/gif');
|
||||
return response(file_get_contents(public_path('uploads/barcodes/invalid_barcode.gif')))->header('Content-type', 'image/gif');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,28 +4,27 @@ namespace App\Http\Controllers\Components;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\AssetFileRequest;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Component;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use enshrined\svgSanitize\Sanitizer;
|
||||
|
||||
class ComponentsFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Validates and stores files associated with a component.
|
||||
*
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param AssetFileRequest $request
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $componentId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*@author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
*/
|
||||
public function store(AssetFileRequest $request, $componentId = null)
|
||||
public function store(UploadFileRequest $request, $componentId = null)
|
||||
{
|
||||
|
||||
if (config('app.lock_passwords')) {
|
||||
@@ -43,30 +42,7 @@ class ComponentsFilesController extends Controller
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$file_name = 'component-'.$component->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
|
||||
|
||||
|
||||
// Check for SVG and sanitize it
|
||||
if ($extension == 'svg') {
|
||||
\Log::debug('This is an SVG');
|
||||
\Log::debug($file_name);
|
||||
|
||||
$sanitizer = new Sanitizer();
|
||||
$dirtySVG = file_get_contents($file->getRealPath());
|
||||
$cleanSVG = $sanitizer->sanitize($dirtySVG);
|
||||
|
||||
try {
|
||||
Storage::put('private_uploads/components/'.$file_name, $cleanSVG);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Upload no workie :( ');
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
} else {
|
||||
Storage::put('private_uploads/components/'.$file_name, file_get_contents($file));
|
||||
}
|
||||
$file_name = $request->handleFile('private_uploads/components/','component-'.$component->id, $file);
|
||||
|
||||
//Log the upload to the log
|
||||
$component->logUpload($file_name, e($request->input('notes')));
|
||||
|
||||
@@ -76,7 +76,6 @@ class ConsumableCheckoutController extends Controller
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.checkout.unavailable'));
|
||||
}
|
||||
|
||||
|
||||
$admin_user = Auth::user();
|
||||
$assigned_to = e($request->input('assigned_to'));
|
||||
|
||||
|
||||
@@ -4,28 +4,27 @@ namespace App\Http\Controllers\Consumables;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\AssetFileRequest;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Consumable;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Consumable\HttpFoundation\JsonResponse;
|
||||
use enshrined\svgSanitize\Sanitizer;
|
||||
|
||||
class ConsumablesFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Validates and stores files associated with a consumable.
|
||||
*
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param AssetFileRequest $request
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $consumableId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*@author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
*/
|
||||
public function store(AssetFileRequest $request, $consumableId = null)
|
||||
public function store(UploadFileRequest $request, $consumableId = null)
|
||||
{
|
||||
if (config('app.lock_passwords')) {
|
||||
return redirect()->route('consumables.show', ['consumable'=>$consumableId])->with('error', trans('general.feature_disabled'));
|
||||
@@ -42,30 +41,7 @@ class ConsumablesFilesController extends Controller
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$file_name = 'consumable-'.$consumable->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
|
||||
|
||||
|
||||
// Check for SVG and sanitize it
|
||||
if ($extension == 'svg') {
|
||||
\Log::debug('This is an SVG');
|
||||
\Log::debug($file_name);
|
||||
|
||||
$sanitizer = new Sanitizer();
|
||||
$dirtySVG = file_get_contents($file->getRealPath());
|
||||
$cleanSVG = $sanitizer->sanitize($dirtySVG);
|
||||
|
||||
try {
|
||||
Storage::put('private_uploads/consumables/'.$file_name, $cleanSVG);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Upload no workie :( ');
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
} else {
|
||||
Storage::put('private_uploads/consumables/'.$file_name, file_get_contents($file));
|
||||
}
|
||||
$file_name = $request->handleFile('private_uploads/consumables/','consumable-'.$consumable->id, $file);
|
||||
|
||||
//Log the upload to the log
|
||||
$consumable->logUpload($file_name, e($request->input('notes')));
|
||||
|
||||
@@ -4,28 +4,27 @@ namespace App\Http\Controllers\Licenses;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\AssetFileRequest;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\License;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use enshrined\svgSanitize\Sanitizer;
|
||||
|
||||
class LicenseFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Validates and stores files associated with a license.
|
||||
*
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param AssetFileRequest $request
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $licenseId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*@author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
*/
|
||||
public function store(AssetFileRequest $request, $licenseId = null)
|
||||
public function store(UploadFileRequest $request, $licenseId = null)
|
||||
{
|
||||
$license = License::find($licenseId);
|
||||
|
||||
@@ -38,30 +37,7 @@ class LicenseFilesController extends Controller
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$file_name = 'license-'.$license->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
|
||||
|
||||
|
||||
// Check for SVG and sanitize it
|
||||
if ($extension == 'svg') {
|
||||
\Log::debug('This is an SVG');
|
||||
\Log::debug($file_name);
|
||||
|
||||
$sanitizer = new Sanitizer();
|
||||
$dirtySVG = file_get_contents($file->getRealPath());
|
||||
$cleanSVG = $sanitizer->sanitize($dirtySVG);
|
||||
|
||||
try {
|
||||
Storage::put('private_uploads/licenses/'.$file_name, $cleanSVG);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Upload no workie :( ');
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
} else {
|
||||
Storage::put('private_uploads/licenses/'.$file_name, file_get_contents($file));
|
||||
}
|
||||
$file_name = $request->handleFile('private_uploads/licenses/','license-'.$license->id, $file);
|
||||
|
||||
//Log the upload to the log
|
||||
$license->logUpload($file_name, e($request->input('notes')));
|
||||
|
||||
@@ -168,7 +168,7 @@ class LocationsController extends Controller
|
||||
{
|
||||
$this->authorize('delete', Location::class);
|
||||
if (is_null($location = Location::find($locationId))) {
|
||||
return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.not_found'));
|
||||
return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.does_not_exist'));
|
||||
}
|
||||
|
||||
if ($location->users()->count() > 0) {
|
||||
|
||||
@@ -295,7 +295,7 @@ 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) ? $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,
|
||||
@@ -616,7 +616,7 @@ class ReportsController extends Controller
|
||||
}
|
||||
|
||||
if ($request->filled('url')) {
|
||||
$header[] = trans('admin/manufacturers/table.url');
|
||||
$header[] = trans('general.url');
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ use App\Http\Requests\SlackSettingsRequest;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Carbon\Carbon;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Settings for
|
||||
@@ -356,6 +357,7 @@ class SettingsController extends Controller
|
||||
}
|
||||
|
||||
$setting->default_eula_text = $request->input('default_eula_text');
|
||||
$setting->load_remote = $request->input('load_remote', 0);
|
||||
$setting->thumbnail_max_h = $request->input('thumbnail_max_h');
|
||||
$setting->privacy_policy_link = $request->input('privacy_policy_link');
|
||||
|
||||
@@ -635,21 +637,21 @@ class SettingsController extends Controller
|
||||
// Check if the audit interval has changed - if it has, we want to update ALL of the assets audit dates
|
||||
if ($request->input('audit_interval') != $setting->audit_interval) {
|
||||
|
||||
// Be careful - this could be a negative number
|
||||
// This could be a negative number if the user is trying to set the audit interval to a lower number than it was before
|
||||
$audit_diff_months = ((int)$request->input('audit_interval') - (int)($setting->audit_interval));
|
||||
|
||||
// Batch update the dates. We have to use this method to avoid time limit exceeded errors on very large datasets,
|
||||
// but it DOES mean this change doesn't get logged in the action logs, since it skips the observer.
|
||||
// @see https://stackoverflow.com/questions/54879160/laravel-observer-not-working-on-bulk-insert
|
||||
$affected = Asset::whereNotNull('next_audit_date')
|
||||
->whereNull('deleted_at')
|
||||
->update(
|
||||
['next_audit_date' => DB::raw('DATE_ADD(next_audit_date, INTERVAL '.$audit_diff_months.' MONTH)')]
|
||||
);
|
||||
|
||||
\Log::debug($affected .' assets affected by audit interval update');
|
||||
|
||||
|
||||
// Grab all of the assets that have an existing next_audit_date
|
||||
$assets = Asset::whereNotNull('next_audit_date')->get();
|
||||
|
||||
// Update all of the assets' next_audit_date values
|
||||
foreach ($assets as $asset) {
|
||||
|
||||
if ($asset->next_audit_date != '') {
|
||||
$old_next_audit = new \DateTime($asset->next_audit_date);
|
||||
$asset->next_audit_date = $old_next_audit->modify($audit_diff_months.' month')->format('Y-m-d');
|
||||
$asset->forceSave();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$alert_email = rtrim($request->input('alert_email'), ',');
|
||||
|
||||
@@ -4,14 +4,13 @@ namespace App\Http\Controllers\Users;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\AssetFileRequest;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use enshrined\svgSanitize\Sanitizer;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class UserFilesController extends Controller
|
||||
@@ -19,14 +18,14 @@ class UserFilesController extends Controller
|
||||
/**
|
||||
* Return JSON response with a list of user details for the getIndex() view.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.6]
|
||||
* @param AssetFileRequest $request
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $userId
|
||||
* @return string JSON
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*@author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.6]
|
||||
*/
|
||||
public function store(AssetFileRequest $request, $userId = null)
|
||||
public function store(UploadFileRequest $request, $userId = null)
|
||||
{
|
||||
$user = User::find($userId);
|
||||
$destinationPath = config('app.private_uploads').'/users';
|
||||
@@ -41,31 +40,7 @@ class UserFilesController extends Controller
|
||||
return redirect()->back()->with('error', trans('admin/users/message.upload.nofiles'));
|
||||
}
|
||||
foreach ($files as $file) {
|
||||
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$file_name = 'user-'.$user->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
|
||||
|
||||
|
||||
// Check for SVG and sanitize it
|
||||
if ($extension == 'svg') {
|
||||
\Log::debug('This is an SVG');
|
||||
\Log::debug($file_name);
|
||||
|
||||
$sanitizer = new Sanitizer();
|
||||
|
||||
$dirtySVG = file_get_contents($file->getRealPath());
|
||||
$cleanSVG = $sanitizer->sanitize($dirtySVG);
|
||||
|
||||
try {
|
||||
Storage::put('private_uploads/users/'.$file_name, $cleanSVG);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Upload no workie :( ');
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
} else {
|
||||
Storage::put('private_uploads/users/'.$file_name, file_get_contents($file));
|
||||
}
|
||||
$file_name = $request->handleFile('private_uploads/users/', 'user-'.$user->id, $file);
|
||||
|
||||
//Log the uploaded file to the log
|
||||
$logAction = new Actionlog();
|
||||
|
||||
@@ -37,23 +37,33 @@ class SlackSettingsForm extends Component
|
||||
|
||||
public function mount() {
|
||||
$this->webhook_text= [
|
||||
"slack" => array(
|
||||
"slack" => array(
|
||||
"name" => trans('admin/settings/general.slack') ,
|
||||
"icon" => 'fab fa-slack',
|
||||
"placeholder" => "https://hooks.slack.com/services/XXXXXXXXXXXXXXXXXXXXX",
|
||||
"link" => 'https://api.slack.com/messaging/webhooks',
|
||||
"icon" => 'fab fa-slack',
|
||||
"placeholder" => "https://hooks.slack.com/services/XXXXXXXXXXXXXXXXXXXXX",
|
||||
"link" => 'https://api.slack.com/messaging/webhooks',
|
||||
"test" => "testWebhook"
|
||||
),
|
||||
"general"=> array(
|
||||
"name" => trans('admin/settings/general.general_webhook'),
|
||||
"icon" => "fab fa-hashtag",
|
||||
"placeholder" => trans('general.url'),
|
||||
"link" => "",
|
||||
"test" => "testWebhook"
|
||||
),
|
||||
"google" => array(
|
||||
"name" => trans('admin/settings/general.google_workspaces'),
|
||||
"icon" => "fa-brands fa-google",
|
||||
"placeholder" => "https://chat.googleapis.com/v1/spaces/xxxxxxxx/messages?key=xxxxxx",
|
||||
"link" => "https://developers.google.com/chat/how-tos/webhooks#register_the_incoming_webhook",
|
||||
"test" => "googleWebhookTest"
|
||||
),
|
||||
"microsoft" => array(
|
||||
"name" => trans('admin/settings/general.ms_teams'),
|
||||
"icon" => "fa-brands fa-microsoft",
|
||||
"placeholder" => "https://abcd.webhook.office.com/webhookb2/XXXXXXX",
|
||||
"link" => "https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook?tabs=dotnet#create-incoming-webhooks-1",
|
||||
"test" => "msTeamTestWebhook"
|
||||
),
|
||||
];
|
||||
|
||||
@@ -64,10 +74,14 @@ class SlackSettingsForm extends Component
|
||||
$this->webhook_icon = $this->webhook_text[$this->setting->webhook_selected]["icon"];
|
||||
$this->webhook_placeholder = $this->webhook_text[$this->setting->webhook_selected]["placeholder"];
|
||||
$this->webhook_link = $this->webhook_text[$this->setting->webhook_selected]["link"];
|
||||
$this->webhook_test = $this->webhook_text[$this->setting->webhook_selected]["test"];
|
||||
$this->webhook_endpoint = $this->setting->webhook_endpoint;
|
||||
$this->webhook_channel = $this->setting->webhook_channel;
|
||||
$this->webhook_botname = $this->setting->webhook_botname;
|
||||
$this->webhook_options = $this->setting->webhook_selected;
|
||||
if($this->webhook_selected == 'microsoft' || $this->webhook_selected == 'google'){
|
||||
$this->webhook_channel = '#NA';
|
||||
}
|
||||
|
||||
|
||||
if($this->setting->webhook_endpoint != null && $this->setting->webhook_channel != null){
|
||||
@@ -87,10 +101,14 @@ class SlackSettingsForm extends Component
|
||||
$this->webhook_placeholder = $this->webhook_text[$this->webhook_selected]["placeholder"];
|
||||
$this->webhook_endpoint = null;
|
||||
$this->webhook_link = $this->webhook_text[$this->webhook_selected]["link"];
|
||||
$this->webhook_test = $this->webhook_text[$this->webhook_selected]["test"];
|
||||
if($this->webhook_selected != 'slack'){
|
||||
$this->isDisabled= '';
|
||||
$this->save_button = trans('general.save');
|
||||
}
|
||||
if($this->webhook_selected == 'microsoft' || $this->webhook_selected == 'google'){
|
||||
$this->webhook_channel = '#NA';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -151,6 +169,7 @@ class SlackSettingsForm extends Component
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function clearSettings(){
|
||||
|
||||
if (Helper::isDemoMode()) {
|
||||
@@ -187,7 +206,35 @@ class SlackSettingsForm extends Component
|
||||
}
|
||||
|
||||
}
|
||||
public function msTeamTestWebhook(){
|
||||
public function googleWebhookTest(){
|
||||
|
||||
$payload = [
|
||||
"text" => trans('general.webhook_test_msg', ['app' => $this->webhook_name]),
|
||||
];
|
||||
|
||||
try {
|
||||
$response = Http::withHeaders([
|
||||
'content-type' => 'applications/json',
|
||||
])->post($this->webhook_endpoint,
|
||||
$payload)->throw();
|
||||
|
||||
|
||||
if (($response->getStatusCode() == 302) || ($response->getStatusCode() == 301)) {
|
||||
return session()->flash('error', trans('admin/settings/message.webhook.error_redirect', ['endpoint' => $this->webhook_endpoint]));
|
||||
}
|
||||
|
||||
$this->isDisabled='';
|
||||
$this->save_button = trans('general.save');
|
||||
return session()->flash('success' , trans('admin/settings/message.webhook.success', ['webhook_name' => $this->webhook_name]));
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
$this->isDisabled='disabled';
|
||||
$this->save_button = trans('admin/settings/general.webhook_presave');
|
||||
return session()->flash('error' , trans('admin/settings/message.webhook.error', ['error_message' => $e->getMessage(), 'app' => $this->webhook_name]));
|
||||
}
|
||||
}
|
||||
public function msTeamTestWebhook(){
|
||||
|
||||
$payload =
|
||||
[
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
class AssetFileRequest 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()
|
||||
{
|
||||
$max_file_size = \App\Helpers\Helper::file_upload_max_size();
|
||||
|
||||
return [
|
||||
'file.*' => 'required|mimes:png,gif,jpg,svg,jpeg,doc,docx,pdf,txt,zip,rar,xls,xlsx,lic,xml,rtf,json,webp|max:'.$max_file_size,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -103,16 +103,35 @@ class ImageUploadRequest extends Request
|
||||
\Log::info('File name will be: '.$file_name);
|
||||
\Log::debug('File extension is: '.$ext);
|
||||
|
||||
if (($image->getClientOriginalExtension() !== 'webp') && ($image->getClientOriginalExtension() !== 'svg')) {
|
||||
if ($image->getMimeType() == 'image/webp') {
|
||||
// If the file is a webp, we need to just move it since webp support
|
||||
// needs to be compiled into gd for resizing to be available
|
||||
|
||||
\Log::debug('This is a webp, just move it');
|
||||
Storage::disk('public')->put($path.'/'.$file_name, file_get_contents($image));
|
||||
} elseif($image->getMimeType() == 'image/svg+xml') {
|
||||
// If the file is an SVG, we need to clean it and NOT encode it
|
||||
\Log::debug('This is an SVG');
|
||||
$sanitizer = new Sanitizer();
|
||||
$dirtySVG = file_get_contents($image->getRealPath());
|
||||
$cleanSVG = $sanitizer->sanitize($dirtySVG);
|
||||
|
||||
try {
|
||||
Storage::disk('public')->put($path . '/' . $file_name, $cleanSVG);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
} else {
|
||||
|
||||
\Log::debug('Not an SVG or webp - resize');
|
||||
\Log::debug('Trying to upload to: '.$path.'/'.$file_name);
|
||||
|
||||
try {
|
||||
$upload = Image::make($image->getRealPath())->resize(null, $w, function ($constraint) {
|
||||
$upload = Image::make($image->getRealPath())->setFileInfoFromPath($image->getRealPath())->resize(null, $w, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
});
|
||||
})->orientate();
|
||||
|
||||
} catch(NotReadableException $e) {
|
||||
\Log::debug($e);
|
||||
$validator = \Validator::make([], []);
|
||||
@@ -124,27 +143,6 @@ class ImageUploadRequest extends Request
|
||||
// This requires a string instead of an object, so we use ($string)
|
||||
Storage::disk('public')->put($path.'/'.$file_name, (string) $upload->encode());
|
||||
|
||||
} else {
|
||||
// If the file is a webp, we need to just move it since webp support
|
||||
// needs to be compiled into gd for resizing to be available
|
||||
if ($image->getClientOriginalExtension() == 'webp') {
|
||||
\Log::debug('This is a webp, just move it');
|
||||
Storage::disk('public')->put($path.'/'.$file_name, file_get_contents($image));
|
||||
// If the file is an SVG, we need to clean it and NOT encode it
|
||||
} else {
|
||||
\Log::debug('This is an SVG');
|
||||
$sanitizer = new Sanitizer();
|
||||
$dirtySVG = file_get_contents($image->getRealPath());
|
||||
$cleanSVG = $sanitizer->sanitize($dirtySVG);
|
||||
|
||||
try {
|
||||
\Log::debug('Trying to upload to: '.$path.'/'.$file_name);
|
||||
Storage::disk('public')->put($path.'/'.$file_name, $cleanSVG);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Upload no workie :( ');
|
||||
\Log::debug($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove Current image if exists
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use enshrined\svgSanitize\Sanitizer;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class UploadFileRequest 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()
|
||||
{
|
||||
$max_file_size = \App\Helpers\Helper::file_upload_max_size();
|
||||
|
||||
return [
|
||||
'file.*' => 'required|mimes:png,gif,jpg,svg,jpeg,doc,docx,pdf,txt,zip,rar,xls,xlsx,lic,xml,rtf,json,webp|max:'.$max_file_size,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes (if needed) and Saves a file to the appropriate location
|
||||
* Returns the 'short' (storage-relative) filename
|
||||
*
|
||||
* TODO - this has a lot of similarities to UploadImageRequest's handleImage; is there
|
||||
* a way to merge them or extend one into the other?
|
||||
*/
|
||||
public function handleFile(string $dirname, string $name_prefix, $file): string
|
||||
{
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$file_name = $name_prefix.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$file->guessExtension();
|
||||
|
||||
|
||||
\Log::debug("Your filetype IS: ".$file->getMimeType());
|
||||
// Check for SVG and sanitize it
|
||||
if ($file->getMimeType() === 'image/svg+xml') {
|
||||
\Log::debug('This is an SVG');
|
||||
\Log::debug($file_name);
|
||||
|
||||
$sanitizer = new Sanitizer();
|
||||
$dirtySVG = file_get_contents($file->getRealPath());
|
||||
$cleanSVG = $sanitizer->sanitize($dirtySVG);
|
||||
|
||||
try {
|
||||
Storage::put($dirname.$file_name, $cleanSVG);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Upload no workie :( ');
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
} else {
|
||||
$put_results = Storage::put($dirname.$file_name, file_get_contents($file));
|
||||
\Log::debug("Here are the '$put_results' (should be 0 or 1 or true or false or something?)");
|
||||
}
|
||||
return $file_name;
|
||||
}
|
||||
}
|
||||
@@ -28,12 +28,20 @@ class AssetMaintenancesTransformer
|
||||
'id' => (int) $assetmaintenance->asset->id,
|
||||
'name'=> ($assetmaintenance->asset->name) ? e($assetmaintenance->asset->name) : null,
|
||||
'asset_tag'=> e($assetmaintenance->asset->asset_tag),
|
||||
|
||||
'serial'=> e($assetmaintenance->asset->serial),
|
||||
'deleted_at'=> e($assetmaintenance->asset->deleted_at),
|
||||
'created_at'=> e($assetmaintenance->asset->created_at),
|
||||
] : null,
|
||||
'model' => (($assetmaintenance->asset) && ($assetmaintenance->asset->model)) ? [
|
||||
'id' => (int) $assetmaintenance->asset->model->id,
|
||||
'name'=> ($assetmaintenance->asset->model->name) ? e($assetmaintenance->asset->model->name).' '.e($assetmaintenance->asset->model->model_number) : null,
|
||||
] : null,
|
||||
'status_label' => ($assetmaintenance->asset->assetstatus) ? [
|
||||
'id' => (int) $assetmaintenance->asset->assetstatus->id,
|
||||
'name'=> e($assetmaintenance->asset->assetstatus->name),
|
||||
'status_type'=> e($assetmaintenance->asset->assetstatus->getStatuslabelType()),
|
||||
'status_meta' => e($assetmaintenance->asset->present()->statusMeta),
|
||||
] : null,
|
||||
'company' => (($assetmaintenance->asset) && ($assetmaintenance->asset->company)) ? [
|
||||
'id' => (int) $assetmaintenance->asset->company->id,
|
||||
'name'=> ($assetmaintenance->asset->company->name) ? e($assetmaintenance->asset->company->name) : null,
|
||||
@@ -64,7 +72,7 @@ class AssetMaintenancesTransformer
|
||||
];
|
||||
|
||||
$permissions_array['available_actions'] = [
|
||||
'update' => Gate::allows('update', Asset::class),
|
||||
'update' => (Gate::allows('update', Asset::class) && ($assetmaintenance->asset->deleted_at=='')) ? true : false,
|
||||
'delete' => Gate::allows('delete', Asset::class),
|
||||
];
|
||||
|
||||
|
||||
@@ -46,10 +46,9 @@ class AccessoryImporter extends ItemImporter
|
||||
$this->item['min_amt'] = $this->findCsvMatch($row, "min_amt");
|
||||
$accessory->fill($this->sanitizeItemForStoring($accessory));
|
||||
|
||||
//FIXME: this disables model validation. Need to find a way to avoid double-logs without breaking everything.
|
||||
// $accessory->unsetEventDispatcher();
|
||||
// This sets an attribute on the Loggable trait for the action log
|
||||
$accessory->setImported(true);
|
||||
if ($accessory->save()) {
|
||||
$accessory->logCreate('Imported using CSV Importer');
|
||||
$this->log('Accessory '.$this->item['name'].' was created');
|
||||
|
||||
return;
|
||||
|
||||
@@ -135,10 +135,10 @@ class AssetImporter extends ItemImporter
|
||||
$asset->{$custom_field} = $val;
|
||||
}
|
||||
}
|
||||
|
||||
// This sets an attribute on the Loggable trait for the action log
|
||||
$asset->setImported(true);
|
||||
if ($asset->save()) {
|
||||
|
||||
$asset->logCreate(trans('general.importer.import_note'));
|
||||
$this->log('Asset '.$this->item['name'].' with serial number '.$this->item['serial'].' was created');
|
||||
|
||||
// If we have a target to checkout to, lets do so.
|
||||
|
||||
@@ -48,10 +48,10 @@ class ComponentImporter extends ItemImporter
|
||||
$this->log('No matching component, creating one');
|
||||
$component = new Component;
|
||||
$component->fill($this->sanitizeItemForStoring($component));
|
||||
//FIXME: this disables model validation. Need to find a way to avoid double-logs without breaking everything.
|
||||
$component->unsetEventDispatcher();
|
||||
|
||||
// This sets an attribute on the Loggable trait for the action log
|
||||
$component->setImported(true);
|
||||
if ($component->save()) {
|
||||
$component->logCreate('Imported using CSV Importer');
|
||||
$this->log('Component '.$this->item['name'].' was created');
|
||||
|
||||
// If we have an asset tag, checkout to that asset.
|
||||
|
||||
@@ -45,10 +45,10 @@ class ConsumableImporter extends ItemImporter
|
||||
$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();
|
||||
|
||||
// This sets an attribute on the Loggable trait for the action log
|
||||
$consumable->setImported(true);
|
||||
if ($consumable->save()) {
|
||||
$consumable->logCreate('Imported using CSV Importer');
|
||||
$this->log('Consumable '.$this->item['name'].' was created');
|
||||
|
||||
return;
|
||||
|
||||
@@ -85,10 +85,10 @@ class LicenseImporter extends ItemImporter
|
||||
} else {
|
||||
$license->fill($this->sanitizeItemForStoring($license));
|
||||
}
|
||||
//FIXME: this disables model validation. Need to find a way to avoid double-logs without breaking everything.
|
||||
// $license->unsetEventDispatcher();
|
||||
|
||||
// This sets an attribute on the Loggable trait for the action log
|
||||
$license->setImported(true);
|
||||
if ($license->save()) {
|
||||
$license->logCreate('Imported using csv importer');
|
||||
$this->log('License '.$this->item['name'].' with serial number '.$this->item['serial'].' was created');
|
||||
|
||||
// Lets try to checkout seats if the fields exist and we have seats.
|
||||
|
||||
@@ -60,16 +60,18 @@ class CheckoutableListener
|
||||
if ($this->shouldSendWebhookNotification()) {
|
||||
|
||||
//slack doesn't include the url in its messaging format so this is needed to hit the endpoint
|
||||
if(Setting::getSettings()->webhook_selected =='slack') {
|
||||
|
||||
if(Setting::getSettings()->webhook_selected =='slack' || Setting::getSettings()->webhook_selected =='general') {
|
||||
|
||||
|
||||
Notification::route('slack', Setting::getSettings()->webhook_endpoint)
|
||||
->notify($this->getCheckoutNotification($event));
|
||||
}
|
||||
}
|
||||
} catch (ClientException $e) {
|
||||
Log::debug("Exception caught during checkout notification: " . $e->getMessage());
|
||||
Log::warning("Exception caught during checkout notification: " . $e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
Log::error("Exception caught during checkout notification: " . $e->getMessage());
|
||||
Log::warning("Exception caught during checkout notification: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +115,7 @@ class CheckoutableListener
|
||||
);
|
||||
}
|
||||
//slack doesn't include the url in its messaging format so this is needed to hit the endpoint
|
||||
if(Setting::getSettings()->webhook_selected =='slack') {
|
||||
if(Setting::getSettings()->webhook_selected =='slack' || Setting::getSettings()->webhook_selected =='general') {
|
||||
|
||||
if ($this->shouldSendWebhookNotification()) {
|
||||
Notification::route('slack', Setting::getSettings()->webhook_endpoint)
|
||||
@@ -122,9 +124,9 @@ class CheckoutableListener
|
||||
}
|
||||
|
||||
} catch (ClientException $e) {
|
||||
Log::debug("Exception caught during checkout notification: " . $e->getMessage());
|
||||
Log::warning("Exception caught during checkout notification: " . $e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
Log::error("Exception caught during checkin notification: " . $e->getMessage());
|
||||
Log::warning("Exception caught during checkin notification: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,9 @@ class Actionlog extends SnipeModel
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
// This is to manually set the source (via setActionSource()) for determineActionSource()
|
||||
protected ?string $source = null;
|
||||
|
||||
protected $presenter = \App\Presenters\ActionlogPresenter::class;
|
||||
use SoftDeletes;
|
||||
use Presentable;
|
||||
@@ -341,7 +344,12 @@ class Actionlog extends SnipeModel
|
||||
* @since v6.3.0
|
||||
* @return string
|
||||
*/
|
||||
public function determineActionSource() {
|
||||
public function determineActionSource(): string
|
||||
{
|
||||
// This is a manually set source
|
||||
if($this->source) {
|
||||
return $this->source;
|
||||
}
|
||||
|
||||
// This is an API call
|
||||
if (((request()->header('content-type') && (request()->header('accept'))=='application/json'))
|
||||
@@ -358,4 +366,10 @@ class Actionlog extends SnipeModel
|
||||
return 'cli/unknown';
|
||||
|
||||
}
|
||||
|
||||
// Manually sets $this->source for determineActionSource()
|
||||
public function setActionSource($source = null): void
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1560,7 +1560,7 @@ class Asset extends Depreciable
|
||||
*
|
||||
* In short, this set of statements tells the query builder to ONLY query against an
|
||||
* actual field that's being passed if it doesn't meet known relational fields. This
|
||||
* allows us to query custom fields directly in the assetsv table
|
||||
* allows us to query custom fields directly in the assets table
|
||||
* (regardless of their name) and *skip* any fields that we already know can only be
|
||||
* searched through relational searches that we do earlier in this method.
|
||||
*
|
||||
|
||||
@@ -62,7 +62,15 @@ class AssetMaintenance extends Model implements ICompanyableChild
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['title', 'notes', 'asset_maintenance_type', 'cost', 'start_date', 'completion_date'];
|
||||
protected $searchableAttributes =
|
||||
[
|
||||
'title',
|
||||
'notes',
|
||||
'asset_maintenance_type',
|
||||
'cost',
|
||||
'start_date',
|
||||
'completion_date'
|
||||
];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
@@ -70,9 +78,10 @@ class AssetMaintenance extends Model implements ICompanyableChild
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [
|
||||
'asset' => ['name', 'asset_tag'],
|
||||
'asset' => ['name', 'asset_tag', 'serial'],
|
||||
'asset.model' => ['name', 'model_number'],
|
||||
'asset.supplier' => ['name'],
|
||||
'asset.assetstatus' => ['name'],
|
||||
'supplier' => ['name'],
|
||||
];
|
||||
|
||||
@@ -197,6 +206,7 @@ class AssetMaintenance extends Model implements ICompanyableChild
|
||||
->orderBy('suppliers_maintenances.name', $order);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope to order on admin user
|
||||
*
|
||||
@@ -239,4 +249,33 @@ class AssetMaintenance extends Model implements ICompanyableChild
|
||||
return $query->leftJoin('assets', 'asset_maintenances.asset_id', '=', 'assets.id')
|
||||
->orderBy('assets.name', $order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on serial
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param string $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeOrderByAssetSerial($query, $order)
|
||||
{
|
||||
return $query->leftJoin('assets', 'asset_maintenances.asset_id', '=', 'assets.id')
|
||||
->orderBy('assets.serial', $order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on status label name
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeOrderStatusName($query, $order)
|
||||
{
|
||||
return $query->join('assets as maintained_asset', 'asset_maintenances.asset_id', '=', 'maintained_asset.id')
|
||||
->leftjoin('status_labels as maintained_asset_status', 'maintained_asset_status.id', '=', 'maintained_asset.status_id')
|
||||
->orderBy('maintained_asset_status.name', $order);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,6 +113,14 @@ final class Company extends SnipeModel
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the company id for the current user taking into
|
||||
* account the full multiple company support setting
|
||||
* and if the current user is a super user.
|
||||
*
|
||||
* @param $unescaped_input
|
||||
* @return int|mixed|string|null
|
||||
*/
|
||||
public static function getIdForCurrentUser($unescaped_input)
|
||||
{
|
||||
if (! static::isFullMultipleCompanySupportEnabled()) {
|
||||
|
||||
@@ -8,6 +8,9 @@ use Illuminate\Support\Facades\Auth;
|
||||
|
||||
trait Loggable
|
||||
{
|
||||
// an attribute for setting whether or not the item was imported
|
||||
public ?bool $imported = false;
|
||||
|
||||
/**
|
||||
* @author Daniel Meltzer <dmeltzer.devel@gmail.com>
|
||||
* @since [v3.4]
|
||||
@@ -18,6 +21,11 @@ trait Loggable
|
||||
return $this->morphMany(Actionlog::class, 'item');
|
||||
}
|
||||
|
||||
public function setImported(bool $bool): void
|
||||
{
|
||||
$this->imported = $bool;
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Daniel Meltzer <dmeltzer.devel@gmail.com>
|
||||
* @since [v3.4]
|
||||
|
||||
@@ -352,7 +352,6 @@ class Setting extends Model
|
||||
'ldap_client_tls_cert',
|
||||
'ldap_default_group',
|
||||
'ldap_dept',
|
||||
'ldap_emp_num',
|
||||
'ldap_phone_field',
|
||||
'ldap_jobtitle',
|
||||
'ldap_manager',
|
||||
|
||||
@@ -9,6 +9,11 @@ use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use NotificationChannels\GoogleChat\Card;
|
||||
use NotificationChannels\GoogleChat\GoogleChatChannel;
|
||||
use NotificationChannels\GoogleChat\GoogleChatMessage;
|
||||
use NotificationChannels\GoogleChat\Section;
|
||||
use NotificationChannels\GoogleChat\Widgets\KeyValue;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsChannel;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage;
|
||||
|
||||
@@ -38,13 +43,17 @@ class CheckinAccessoryNotification extends Notification
|
||||
public function via()
|
||||
{
|
||||
$notifyBy = [];
|
||||
if (Setting::getSettings()->webhook_selected == 'google'){
|
||||
|
||||
$notifyBy[] = GoogleChatChannel::class;
|
||||
}
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'microsoft'){
|
||||
|
||||
$notifyBy[] = MicrosoftTeamsChannel::class;
|
||||
}
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'slack') {
|
||||
if (Setting::getSettings()->webhook_selected == 'slack' || Setting::getSettings()->webhook_selected == 'general' ) {
|
||||
$notifyBy[] = 'slack';
|
||||
}
|
||||
|
||||
@@ -54,34 +63,8 @@ class CheckinAccessoryNotification extends Notification
|
||||
if ($this->target instanceof User && $this->target->email != '') {
|
||||
\Log::debug('The target is a user');
|
||||
|
||||
/**
|
||||
* Send an email if the asset requires acceptance,
|
||||
* so the user can accept or decline the asset
|
||||
*/
|
||||
if (($this->item->requireAcceptance()) || ($this->item->getEula()) || ($this->item->checkin_email())) {
|
||||
$notifyBy[] = 'mail';
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an email if the asset requires acceptance,
|
||||
* so the user can accept or decline the asset
|
||||
*/
|
||||
if ($this->item->requireAcceptance()) {
|
||||
\Log::debug('This accessory requires acceptance');
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an email if the item has a EULA, since the user should always receive it
|
||||
*/
|
||||
if ($this->item->getEula()) {
|
||||
\Log::debug('This accessory has a EULA');
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an email if an email should be sent at checkin/checkout
|
||||
*/
|
||||
if ($this->item->checkin_email()) {
|
||||
\Log::debug('This accessory has a checkin_email()');
|
||||
$notifyBy[] = 'mail';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,6 +115,32 @@ class CheckinAccessoryNotification extends Notification
|
||||
->fact(trans('admin/consumables/general.remaining'), $item->numRemaining())
|
||||
->fact(trans('mail.notes'), $note ?: '');
|
||||
}
|
||||
public function toGoogleChat()
|
||||
{
|
||||
$item = $this->item;
|
||||
$note = $this->note;
|
||||
|
||||
return GoogleChatMessage::create()
|
||||
->to($this->settings->webhook_endpoint)
|
||||
->card(
|
||||
Card::create()
|
||||
->header(
|
||||
'<strong>'.trans('mail.Accessory_Checkin_Notification').'</strong>' ?: '',
|
||||
htmlspecialchars_decode($item->present()->name) ?: '',
|
||||
)
|
||||
->section(
|
||||
Section::create(
|
||||
KeyValue::create(
|
||||
trans('mail.checked_into').': '.$item->location->name ? $item->location->name : '',
|
||||
trans('admin/consumables/general.remaining').': '.$item->numRemaining(),
|
||||
trans('admin/hardware/form.notes').": ".$note ?: '',
|
||||
)
|
||||
->onClick(route('accessories.show', $item->id))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
|
||||
@@ -10,6 +10,11 @@ use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use NotificationChannels\GoogleChat\Card;
|
||||
use NotificationChannels\GoogleChat\GoogleChatChannel;
|
||||
use NotificationChannels\GoogleChat\GoogleChatMessage;
|
||||
use NotificationChannels\GoogleChat\Section;
|
||||
use NotificationChannels\GoogleChat\Widgets\KeyValue;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsChannel;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage;
|
||||
|
||||
@@ -46,12 +51,16 @@ class CheckinAssetNotification extends Notification
|
||||
public function via()
|
||||
{
|
||||
$notifyBy = [];
|
||||
if (Setting::getSettings()->webhook_selected == 'google'){
|
||||
|
||||
$notifyBy[] = GoogleChatChannel::class;
|
||||
}
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'microsoft'){
|
||||
|
||||
$notifyBy[] = MicrosoftTeamsChannel::class;
|
||||
}
|
||||
if (Setting::getSettings()->webhook_selected == 'slack') {
|
||||
if (Setting::getSettings()->webhook_selected == 'slack' || Setting::getSettings()->webhook_selected == 'general' ) {
|
||||
\Log::debug('use webhook');
|
||||
$notifyBy[] = 'slack';
|
||||
}
|
||||
@@ -108,6 +117,33 @@ class CheckinAssetNotification extends Notification
|
||||
->fact(trans('admin/hardware/form.status'), $item->assetstatus->name)
|
||||
->fact(trans('mail.notes'), $note ?: '');
|
||||
}
|
||||
public function toGoogleChat()
|
||||
{
|
||||
$target = $this->target;
|
||||
$item = $this->item;
|
||||
$note = $this->note;
|
||||
|
||||
return GoogleChatMessage::create()
|
||||
->to($this->settings->webhook_endpoint)
|
||||
->card(
|
||||
Card::create()
|
||||
->header(
|
||||
'<strong>'.trans('mail.Asset_Checkin_Notification').'</strong>' ?: '',
|
||||
htmlspecialchars_decode($item->present()->name) ?: '',
|
||||
)
|
||||
->section(
|
||||
Section::create(
|
||||
KeyValue::create(
|
||||
trans('mail.checked_into') ?: '',
|
||||
$item->location->name ? $item->location->name : '',
|
||||
trans('admin/hardware/form.status').": ".$item->assetstatus->name,
|
||||
)
|
||||
->onClick(route('hardware.show', $item->id))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
|
||||
@@ -9,6 +9,11 @@ use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use NotificationChannels\GoogleChat\Card;
|
||||
use NotificationChannels\GoogleChat\GoogleChatChannel;
|
||||
use NotificationChannels\GoogleChat\GoogleChatMessage;
|
||||
use NotificationChannels\GoogleChat\Section;
|
||||
use NotificationChannels\GoogleChat\Widgets\KeyValue;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsChannel;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage;
|
||||
|
||||
@@ -43,12 +48,16 @@ class CheckinLicenseSeatNotification extends Notification
|
||||
{
|
||||
$notifyBy = [];
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'google'){
|
||||
|
||||
$notifyBy[] = GoogleChatChannel::class;
|
||||
}
|
||||
if (Setting::getSettings()->webhook_selected == 'microsoft'){
|
||||
|
||||
$notifyBy[] = MicrosoftTeamsChannel::class;
|
||||
}
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'slack') {
|
||||
if (Setting::getSettings()->webhook_selected == 'slack' || Setting::getSettings()->webhook_selected == 'general' ) {
|
||||
$notifyBy[] = 'slack';
|
||||
}
|
||||
|
||||
@@ -113,6 +122,34 @@ class CheckinLicenseSeatNotification extends Notification
|
||||
->fact(trans('admin/consumables/general.remaining'), $item->availCount()->count())
|
||||
->fact(trans('mail.notes'), $note ?: '');
|
||||
}
|
||||
public function toGoogleChat()
|
||||
{
|
||||
$target = $this->target;
|
||||
$item = $this->item;
|
||||
$note = $this->note;
|
||||
|
||||
return GoogleChatMessage::create()
|
||||
->to($this->settings->webhook_endpoint)
|
||||
->card(
|
||||
Card::create()
|
||||
->header(
|
||||
'<strong>'.trans('mail.License_Checkin_Notification').'</strong>' ?: '',
|
||||
htmlspecialchars_decode($item->present()->name) ?: '',
|
||||
)
|
||||
->section(
|
||||
Section::create(
|
||||
KeyValue::create(
|
||||
trans('mail.checkedin_from') ?: '',
|
||||
$target->present()->fullName() ?: '',
|
||||
trans('admin/consumables/general.remaining').': '.$item->availCount()->count(),
|
||||
)
|
||||
->onClick(route('licenses.show', $item->id))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
|
||||
@@ -9,6 +9,11 @@ use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use NotificationChannels\GoogleChat\Card;
|
||||
use NotificationChannels\GoogleChat\GoogleChatChannel;
|
||||
use NotificationChannels\GoogleChat\GoogleChatMessage;
|
||||
use NotificationChannels\GoogleChat\Section;
|
||||
use NotificationChannels\GoogleChat\Widgets\KeyValue;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsChannel;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage;
|
||||
|
||||
@@ -37,13 +42,17 @@ class CheckoutAccessoryNotification extends Notification
|
||||
public function via()
|
||||
{
|
||||
$notifyBy = [];
|
||||
if (Setting::getSettings()->webhook_selected == 'google'){
|
||||
|
||||
$notifyBy[] = GoogleChatChannel::class;
|
||||
}
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'microsoft'){
|
||||
|
||||
$notifyBy[] = MicrosoftTeamsChannel::class;
|
||||
}
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'slack') {
|
||||
if (Setting::getSettings()->webhook_selected == 'slack' || Setting::getSettings()->webhook_selected == 'general' ) {
|
||||
$notifyBy[] = 'slack';
|
||||
}
|
||||
|
||||
@@ -123,6 +132,34 @@ class CheckoutAccessoryNotification extends Notification
|
||||
->fact(trans('mail.notes'), $note ?: '');
|
||||
|
||||
}
|
||||
public function toGoogleChat()
|
||||
{
|
||||
$target = $this->target;
|
||||
$item = $this->item;
|
||||
$note = $this->note;
|
||||
|
||||
return GoogleChatMessage::create()
|
||||
->to($this->settings->webhook_endpoint)
|
||||
->card(
|
||||
Card::create()
|
||||
->header(
|
||||
'<strong>'.trans('mail.Accessory_Checkout_Notification').'</strong>' ?: '',
|
||||
htmlspecialchars_decode($item->present()->name) ?: '',
|
||||
)
|
||||
->section(
|
||||
Section::create(
|
||||
KeyValue::create(
|
||||
trans('mail.assigned_to') ?: '',
|
||||
$target->present()->name ?: '',
|
||||
trans('admin/consumables/general.remaining').": ". $item->numRemaining(),
|
||||
)
|
||||
->onClick(route('users.show', $target->id))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
|
||||
@@ -11,6 +11,13 @@ use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use NotificationChannels\GoogleChat\Card;
|
||||
use NotificationChannels\GoogleChat\Enums\Icon;
|
||||
use NotificationChannels\GoogleChat\Enums\ImageStyle;
|
||||
use NotificationChannels\GoogleChat\GoogleChatChannel;
|
||||
use NotificationChannels\GoogleChat\GoogleChatMessage;
|
||||
use NotificationChannels\GoogleChat\Section;
|
||||
use NotificationChannels\GoogleChat\Widgets\KeyValue;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsChannel;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage;
|
||||
|
||||
@@ -54,13 +61,20 @@ class CheckoutAssetNotification extends Notification
|
||||
*/
|
||||
public function via()
|
||||
{
|
||||
$notifyBy = [];
|
||||
if (Setting::getSettings()->webhook_selected == 'google'){
|
||||
|
||||
$notifyBy[] = GoogleChatChannel::class;
|
||||
}
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'microsoft'){
|
||||
|
||||
return [MicrosoftTeamsChannel::class];
|
||||
$notifyBy[] = MicrosoftTeamsChannel::class;
|
||||
}
|
||||
$notifyBy = [];
|
||||
|
||||
if ((Setting::getSettings()) && (Setting::getSettings()->webhook_selected == 'slack')) {
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'slack' || Setting::getSettings()->webhook_selected == 'general' ) {
|
||||
|
||||
\Log::debug('use webhook');
|
||||
$notifyBy[] = 'slack';
|
||||
}
|
||||
@@ -143,6 +157,33 @@ class CheckoutAssetNotification extends Notification
|
||||
|
||||
|
||||
}
|
||||
public function toGoogleChat()
|
||||
{
|
||||
$target = $this->target;
|
||||
$item = $this->item;
|
||||
$note = $this->note;
|
||||
|
||||
return GoogleChatMessage::create()
|
||||
->to($this->settings->webhook_endpoint)
|
||||
->card(
|
||||
Card::create()
|
||||
->header(
|
||||
'<strong>'.trans('mail.Asset_Checkout_Notification').'</strong>' ?: '',
|
||||
htmlspecialchars_decode($item->present()->name) ?: '',
|
||||
)
|
||||
->section(
|
||||
Section::create(
|
||||
KeyValue::create(
|
||||
trans('mail.assigned_to') ?: '',
|
||||
$target->present()->name ?: '',
|
||||
$note ?: '',
|
||||
)
|
||||
->onClick(route('users.show', $target->id))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
|
||||
@@ -9,6 +9,11 @@ use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use NotificationChannels\GoogleChat\Card;
|
||||
use NotificationChannels\GoogleChat\GoogleChatChannel;
|
||||
use NotificationChannels\GoogleChat\GoogleChatMessage;
|
||||
use NotificationChannels\GoogleChat\Section;
|
||||
use NotificationChannels\GoogleChat\Widgets\KeyValue;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsChannel;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage;
|
||||
|
||||
@@ -44,13 +49,17 @@ class CheckoutConsumableNotification extends Notification
|
||||
public function via()
|
||||
{
|
||||
$notifyBy = [];
|
||||
if (Setting::getSettings()->webhook_selected == 'google'){
|
||||
|
||||
$notifyBy[] = GoogleChatChannel::class;
|
||||
}
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'microsoft'){
|
||||
|
||||
$notifyBy[] = MicrosoftTeamsChannel::class;
|
||||
}
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'slack') {
|
||||
if (Setting::getSettings()->webhook_selected == 'slack' || Setting::getSettings()->webhook_selected == 'general' ) {
|
||||
$notifyBy[] = 'slack';
|
||||
}
|
||||
|
||||
@@ -128,6 +137,33 @@ class CheckoutConsumableNotification extends Notification
|
||||
->fact(trans('admin/consumables/general.remaining'), $item->numRemaining())
|
||||
->fact(trans('mail.notes'), $note ?: '');
|
||||
}
|
||||
public function toGoogleChat()
|
||||
{
|
||||
$target = $this->target;
|
||||
$item = $this->item;
|
||||
$note = $this->note;
|
||||
|
||||
return GoogleChatMessage::create()
|
||||
->to($this->settings->webhook_endpoint)
|
||||
->card(
|
||||
Card::create()
|
||||
->header(
|
||||
'<strong>'.trans('mail.Consumable_checkout_notification').'</strong>' ?: '',
|
||||
htmlspecialchars_decode($item->present()->name) ?: '',
|
||||
)
|
||||
->section(
|
||||
Section::create(
|
||||
KeyValue::create(
|
||||
trans('mail.assigned_to') ?: '',
|
||||
$target->present()->fullName() ?: '',
|
||||
trans('admin/consumables/general.remaining').': '.$item->numRemaining(),
|
||||
)
|
||||
->onClick(route('users.show', $target->id))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
|
||||
@@ -9,6 +9,11 @@ use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use NotificationChannels\GoogleChat\Card;
|
||||
use NotificationChannels\GoogleChat\GoogleChatChannel;
|
||||
use NotificationChannels\GoogleChat\GoogleChatMessage;
|
||||
use NotificationChannels\GoogleChat\Section;
|
||||
use NotificationChannels\GoogleChat\Widgets\KeyValue;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsChannel;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage;
|
||||
|
||||
@@ -43,15 +48,18 @@ class CheckoutLicenseSeatNotification extends Notification
|
||||
*/
|
||||
public function via()
|
||||
{
|
||||
|
||||
$notifyBy = [];
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'google'){
|
||||
|
||||
$notifyBy[] = GoogleChatChannel::class;
|
||||
}
|
||||
if (Setting::getSettings()->webhook_selected == 'microsoft'){
|
||||
|
||||
$notifyBy[] = MicrosoftTeamsChannel::class;
|
||||
}
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'slack') {
|
||||
if (Setting::getSettings()->webhook_selected == 'slack' || Setting::getSettings()->webhook_selected == 'general' ) {
|
||||
$notifyBy[] = 'slack';
|
||||
}
|
||||
|
||||
@@ -129,6 +137,33 @@ class CheckoutLicenseSeatNotification extends Notification
|
||||
->fact(trans('admin/consumables/general.remaining'), $item->availCount()->count())
|
||||
->fact(trans('mail.notes'), $note ?: '');
|
||||
}
|
||||
public function toGoogleChat()
|
||||
{
|
||||
$target = $this->target;
|
||||
$item = $this->item;
|
||||
$note = $this->note;
|
||||
|
||||
return GoogleChatMessage::create()
|
||||
->to($this->settings->webhook_endpoint)
|
||||
->card(
|
||||
Card::create()
|
||||
->header(
|
||||
'<strong>'.trans('mail.License_Checkout_Notification').'</strong>' ?: '',
|
||||
htmlspecialchars_decode($item->present()->name) ?: '',
|
||||
)
|
||||
->section(
|
||||
Section::create(
|
||||
KeyValue::create(
|
||||
trans('mail.assigned_to') ?: '',
|
||||
$target->present()->name ?: '',
|
||||
trans('admin/consumables/general.remaining').': '.$item->availCount()->count(),
|
||||
)
|
||||
->onClick(route('users.show', $target->id))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
|
||||
@@ -38,6 +38,9 @@ class AccessoryObserver
|
||||
$logAction->item_id = $accessory->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->user_id = Auth::id();
|
||||
if($accessory->imported) {
|
||||
$logAction->setActionSource('importer');
|
||||
}
|
||||
$logAction->logaction('create');
|
||||
}
|
||||
|
||||
|
||||
@@ -109,6 +109,9 @@ class AssetObserver
|
||||
$logAction->item_id = $asset->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->user_id = Auth::id();
|
||||
if($asset->imported) {
|
||||
$logAction->setActionSource('importer');
|
||||
}
|
||||
$logAction->logaction('create');
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,9 @@ class ComponentObserver
|
||||
$logAction->item_id = $component->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->user_id = Auth::id();
|
||||
if($component->imported) {
|
||||
$logAction->setActionSource('importer');
|
||||
}
|
||||
$logAction->logaction('create');
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,9 @@ class ConsumableObserver
|
||||
$logAction->item_id = $consumable->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->user_id = Auth::id();
|
||||
if($consumable->imported) {
|
||||
$logAction->setActionSource('importer');
|
||||
}
|
||||
$logAction->logaction('create');
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,9 @@ class LicenseObserver
|
||||
$logAction->item_id = $license->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->user_id = Auth::id();
|
||||
if($license->imported) {
|
||||
$logAction->setActionSource('importer');
|
||||
}
|
||||
$logAction->logaction('create');
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,19 @@ class AssetMaintenancesPresenter extends Presenter
|
||||
'sortable' => true,
|
||||
'title' => trans('admin/hardware/table.asset_tag'),
|
||||
'formatter' => 'assetTagLinkFormatter',
|
||||
], [
|
||||
'field' => 'serial',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'title' => trans('admin/hardware/table.serial'),
|
||||
'formatter' => 'assetSerialLinkFormatter',
|
||||
], [
|
||||
'field' => 'status_label',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'title' => trans('admin/hardware/table.status'),
|
||||
'visible' => true,
|
||||
'formatter' => 'statuslabelsLinkObjFormatter',
|
||||
], [
|
||||
'field' => 'model',
|
||||
'searchable' => true,
|
||||
|
||||
@@ -45,7 +45,7 @@ class ManufacturerPresenter extends Presenter
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('admin/manufacturers/table.url'),
|
||||
'title' => trans('general.url'),
|
||||
'visible' => true,
|
||||
'formatter' => 'externalLinkFormatter',
|
||||
],
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
"guzzlehttp/guzzle": "^7.0.1",
|
||||
"intervention/image": "^2.5",
|
||||
"javiereguiluz/easyslugger": "^1.0",
|
||||
"laravel-notification-channels/google-chat": "^1.0",
|
||||
"laravel-notification-channels/microsoft-teams": "^1.1",
|
||||
"laravel/framework": "^8.46",
|
||||
"laravel/helpers": "^1.4",
|
||||
|
||||
Generated
+80
-23
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "89580c52de91168aac8321460bd428e2",
|
||||
"content-hash": "9cca85cd0074df9154765b1ab52f83fa",
|
||||
"packages": [
|
||||
{
|
||||
"name": "alek13/slack",
|
||||
@@ -3188,6 +3188,63 @@
|
||||
},
|
||||
"time": "2015-04-12T19:57:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel-notification-channels/google-chat",
|
||||
"version": "v1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel-notification-channels/google-chat.git",
|
||||
"reference": "843078439403a925b484cef99a26b447e30a9c32"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel-notification-channels/google-chat/zipball/843078439403a925b484cef99a26b447e30a9c32",
|
||||
"reference": "843078439403a925b484cef99a26b447e30a9c32",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzlehttp/guzzle": "^6.3 || ^7.0",
|
||||
"illuminate/notifications": "~8.0",
|
||||
"illuminate/support": "~8.0",
|
||||
"php": ">=7.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"orchestra/testbench": "^6.0",
|
||||
"phpunit/phpunit": "^9.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"NotificationChannels\\GoogleChat\\GoogleChatServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"NotificationChannels\\GoogleChat\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Frank Dixon",
|
||||
"email": "frank@thetreehouse.family",
|
||||
"homepage": "https://thetreehouse.family",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Google Chat Notification Channel for Laravel (fka. Hangouts Chat)",
|
||||
"homepage": "https://github.com/laravel-notification-channels/google-chat",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel-notification-channels/google-chat/issues",
|
||||
"source": "https://github.com/laravel-notification-channels/google-chat/tree/v1.0.1"
|
||||
},
|
||||
"time": "2021-07-15T22:40:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel-notification-channels/microsoft-teams",
|
||||
"version": "v1.1.4",
|
||||
@@ -4747,16 +4804,16 @@
|
||||
},
|
||||
{
|
||||
"name": "league/oauth2-server",
|
||||
"version": "8.3.5",
|
||||
"version": "8.4.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/oauth2-server.git",
|
||||
"reference": "7aeb7c42b463b1a6fe4d084d3145e2fa22436876"
|
||||
"reference": "007dc5f6c0151a73b133fec36c9686cc956209d3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/oauth2-server/zipball/7aeb7c42b463b1a6fe4d084d3145e2fa22436876",
|
||||
"reference": "7aeb7c42b463b1a6fe4d084d3145e2fa22436876",
|
||||
"url": "https://api.github.com/repos/thephpleague/oauth2-server/zipball/007dc5f6c0151a73b133fec36c9686cc956209d3",
|
||||
"reference": "007dc5f6c0151a73b133fec36c9686cc956209d3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4823,7 +4880,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/thephpleague/oauth2-server/issues",
|
||||
"source": "https://github.com/thephpleague/oauth2-server/tree/8.3.5"
|
||||
"source": "https://github.com/thephpleague/oauth2-server/tree/8.4.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4831,7 +4888,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-03T21:21:28+00:00"
|
||||
"time": "2023-08-02T22:54:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/uri",
|
||||
@@ -9612,16 +9669,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-kernel",
|
||||
"version": "v5.4.10",
|
||||
"version": "v5.4.20",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-kernel.git",
|
||||
"reference": "255ae3b0a488d78fbb34da23d3e0c059874b5948"
|
||||
"reference": "aaeec341582d3c160cc9ecfa8b2419ba6c69954e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/255ae3b0a488d78fbb34da23d3e0c059874b5948",
|
||||
"reference": "255ae3b0a488d78fbb34da23d3e0c059874b5948",
|
||||
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/aaeec341582d3c160cc9ecfa8b2419ba6c69954e",
|
||||
"reference": "aaeec341582d3c160cc9ecfa8b2419ba6c69954e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -9704,7 +9761,7 @@
|
||||
"description": "Provides a structured process for converting a Request into a Response",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/http-kernel/tree/v5.4.10"
|
||||
"source": "https://github.com/symfony/http-kernel/tree/v5.4.20"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -9720,7 +9777,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-06-26T16:57:59+00:00"
|
||||
"time": "2023-02-01T08:18:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/mime",
|
||||
@@ -12590,16 +12647,16 @@
|
||||
},
|
||||
{
|
||||
"name": "composer/composer",
|
||||
"version": "2.6.6",
|
||||
"version": "2.7.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/composer/composer.git",
|
||||
"reference": "683557bd2466072777309d039534bb1332d0dda5"
|
||||
"reference": "aaf6ed5ccd27c23f79a545e351b4d7842a99d0bc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/composer/composer/zipball/683557bd2466072777309d039534bb1332d0dda5",
|
||||
"reference": "683557bd2466072777309d039534bb1332d0dda5",
|
||||
"url": "https://api.github.com/repos/composer/composer/zipball/aaf6ed5ccd27c23f79a545e351b4d7842a99d0bc",
|
||||
"reference": "aaf6ed5ccd27c23f79a545e351b4d7842a99d0bc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -12617,7 +12674,7 @@
|
||||
"seld/jsonlint": "^1.4",
|
||||
"seld/phar-utils": "^1.2",
|
||||
"seld/signal-handler": "^2.0",
|
||||
"symfony/console": "^5.4.11 || ^6.0.11",
|
||||
"symfony/console": "^5.4.11 || ^6.0.11 || ^7",
|
||||
"symfony/filesystem": "^5.4 || ^6.0 || ^7",
|
||||
"symfony/finder": "^5.4 || ^6.0 || ^7",
|
||||
"symfony/polyfill-php73": "^1.24",
|
||||
@@ -12631,7 +12688,7 @@
|
||||
"phpstan/phpstan-phpunit": "^1.0",
|
||||
"phpstan/phpstan-strict-rules": "^1",
|
||||
"phpstan/phpstan-symfony": "^1.2.10",
|
||||
"symfony/phpunit-bridge": "^6.0 || ^7"
|
||||
"symfony/phpunit-bridge": "^6.4.1 || ^7.0.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages",
|
||||
@@ -12644,7 +12701,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "2.6-dev"
|
||||
"dev-main": "2.7-dev"
|
||||
},
|
||||
"phpstan": {
|
||||
"includes": [
|
||||
@@ -12684,7 +12741,7 @@
|
||||
"irc": "ircs://irc.libera.chat:6697/composer",
|
||||
"issues": "https://github.com/composer/composer/issues",
|
||||
"security": "https://github.com/composer/composer/security/policy",
|
||||
"source": "https://github.com/composer/composer/tree/2.6.6"
|
||||
"source": "https://github.com/composer/composer/tree/2.7.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -12700,7 +12757,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-12-08T17:32:26+00:00"
|
||||
"time": "2024-02-09T14:26:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "composer/metadata-minifier",
|
||||
@@ -17031,5 +17088,5 @@
|
||||
"ext-pdo": "*"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.3.0"
|
||||
"plugin-api-version": "2.6.0"
|
||||
}
|
||||
|
||||
+5
-5
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
return array (
|
||||
'app_version' => 'v6.3.0',
|
||||
'full_app_version' => 'v6.3.0 - build 12490-g9136415bb',
|
||||
'build_version' => '12490',
|
||||
'app_version' => 'v6.3.1',
|
||||
'full_app_version' => 'v6.3.1 - build 12672-g00cea3eb3',
|
||||
'build_version' => '12672',
|
||||
'prerelease_version' => '',
|
||||
'hash_version' => 'g9136415bb',
|
||||
'full_hash' => 'v6.3.0-729-g9136415bb',
|
||||
'hash_version' => 'g00cea3eb3',
|
||||
'full_hash' => 'v6.3.1-180-g00cea3eb3',
|
||||
'branch' => 'master',
|
||||
);
|
||||
@@ -8,6 +8,7 @@ use App\Models\Location;
|
||||
use App\Models\Manufacturer;
|
||||
use App\Models\Supplier;
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class AccessoryFactory extends Factory
|
||||
@@ -33,7 +34,7 @@ class AccessoryFactory extends Factory
|
||||
$this->faker->randomElement(['Keyboard', 'Wired'])
|
||||
),
|
||||
'user_id' => User::factory()->superuser(),
|
||||
'category_id' => Category::factory(),
|
||||
'category_id' => Category::factory()->forAccessories(),
|
||||
'model_number' => $this->faker->numberBetween(1000000, 50000000),
|
||||
'location_id' => Location::factory(),
|
||||
'qty' => 1,
|
||||
@@ -114,4 +115,42 @@ class AccessoryFactory extends Factory
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function withoutItemsRemaining()
|
||||
{
|
||||
return $this->state(function () {
|
||||
return [
|
||||
'qty' => 1,
|
||||
];
|
||||
})->afterCreating(function ($accessory) {
|
||||
$user = User::factory()->create();
|
||||
|
||||
$accessory->users()->attach($accessory->id, [
|
||||
'accessory_id' => $accessory->id,
|
||||
'created_at' => now(),
|
||||
'user_id' => $user->id,
|
||||
'assigned_to' => $user->id,
|
||||
'note' => '',
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
public function requiringAcceptance()
|
||||
{
|
||||
return $this->afterCreating(function ($accessory) {
|
||||
$accessory->category->update(['require_acceptance' => 1]);
|
||||
});
|
||||
}
|
||||
|
||||
public function checkedOutToUser(User $user = null)
|
||||
{
|
||||
return $this->afterCreating(function (Accessory $accessory) use ($user) {
|
||||
$accessory->users()->attach($accessory->id, [
|
||||
'accessory_id' => $accessory->id,
|
||||
'created_at' => Carbon::now(),
|
||||
'user_id' => 1,
|
||||
'assigned_to' => $user->id ?? User::factory()->create()->id,
|
||||
]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,4 +172,10 @@ class CategoryFactory extends Factory
|
||||
]);
|
||||
}
|
||||
|
||||
public function forAccessories()
|
||||
{
|
||||
return $this->state([
|
||||
'category_type' => 'accessory',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,4 +91,29 @@ class ConsumableFactory extends Factory
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function withoutItemsRemaining()
|
||||
{
|
||||
return $this->state(function () {
|
||||
return [
|
||||
'qty' => 1,
|
||||
];
|
||||
})->afterCreating(function (Consumable $consumable) {
|
||||
$user = User::factory()->create();
|
||||
|
||||
$consumable->users()->attach($consumable->id, [
|
||||
'consumable_id' => $consumable->id,
|
||||
'user_id' => $user->id,
|
||||
'assigned_to' => $user->id,
|
||||
'note' => '',
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
public function requiringAcceptance()
|
||||
{
|
||||
return $this->afterCreating(function (Consumable $consumable) {
|
||||
$consumable->category->update(['require_acceptance' => 1]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+69
-30
@@ -1565,9 +1565,9 @@
|
||||
}
|
||||
},
|
||||
"@types/eslint": {
|
||||
"version": "8.56.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.1.tgz",
|
||||
"integrity": "sha512-18PLWRzhy9glDQp3+wOgfLYRWlhgX0azxgJ63rdpoUHyrC9z0f5CkFburjQx4uD7ZCruw85ZtMt6K+L+R8fLJQ==",
|
||||
"version": "8.56.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.2.tgz",
|
||||
"integrity": "sha512-uQDwm1wFHmbBbCZCqAlq6Do9LYwByNZHWzXppSnay9SuwJ+VRbjkbLABer54kcPnMSlG6Fdiy2yaFXm/z9Z5gw==",
|
||||
"requires": {
|
||||
"@types/estree": "*",
|
||||
"@types/json-schema": "*"
|
||||
@@ -2350,9 +2350,9 @@
|
||||
}
|
||||
},
|
||||
"alpinejs": {
|
||||
"version": "3.13.3",
|
||||
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.13.3.tgz",
|
||||
"integrity": "sha512-WZ6WQjkAOl+WdW/jukzNHq9zHFDNKmkk/x6WF7WdyNDD6woinrfXCVsZXm0galjbco+pEpYmJLtwlZwcOfIVdg==",
|
||||
"version": "3.13.5",
|
||||
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.13.5.tgz",
|
||||
"integrity": "sha512-1d2XeNGN+Zn7j4mUAKXtAgdc4/rLeadyTMWeJGXF5DzwawPBxwTiBhFFm6w/Ei8eJxUZeyNWWSD9zknfdz1kEw==",
|
||||
"requires": {
|
||||
"@vue/reactivity": "~3.1.1"
|
||||
}
|
||||
@@ -3348,9 +3348,9 @@
|
||||
"integrity": "sha1-EQPWvADPv6jPyaJZmrUYxVZD2j8="
|
||||
},
|
||||
"bootstrap-table": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap-table/-/bootstrap-table-1.22.1.tgz",
|
||||
"integrity": "sha512-Nw8p+BmaiMDSfoer/p49YeI3vJQAWhudxhyKMuqnJBb3NRvCRewMk7JDgiN9SQO3YeSejOirKtcdWpM0dtddWg=="
|
||||
"version": "1.22.2",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap-table/-/bootstrap-table-1.22.2.tgz",
|
||||
"integrity": "sha512-ZjZGcEXm/N7N/wAykmANWKKV+U+7AxgoNuBwWLrKbvAGT8XXS2f0OCiFmuMwpkqg7pDbF+ff9bEf/lOAlxcF1w=="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
@@ -3611,6 +3611,7 @@
|
||||
"version": "4.19.1",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz",
|
||||
"integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"caniuse-lite": "^1.0.30001286",
|
||||
"electron-to-chromium": "^1.4.17",
|
||||
@@ -3731,7 +3732,8 @@
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001292",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001292.tgz",
|
||||
"integrity": "sha512-jnT4Tq0Q4ma+6nncYQVe7d73kmDmE9C3OGTx3MvW7lBM/eY1S1DZTMBON7dqV481RhNiS5OxD7k9JQvmDOTirw=="
|
||||
"integrity": "sha512-jnT4Tq0Q4ma+6nncYQVe7d73kmDmE9C3OGTx3MvW7lBM/eY1S1DZTMBON7dqV481RhNiS5OxD7k9JQvmDOTirw==",
|
||||
"dev": true
|
||||
},
|
||||
"canvg": {
|
||||
"version": "3.0.10",
|
||||
@@ -4931,7 +4933,8 @@
|
||||
"electron-to-chromium": {
|
||||
"version": "1.4.28",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.28.tgz",
|
||||
"integrity": "sha512-Gzbf0wUtKfyPaqf0Plz+Ctinf9eQIzxEqBHwSvbGfeOm9GMNdLxyu1dNiCUfM+x6r4BE0xUJNh3Nmg9gfAtTmg=="
|
||||
"integrity": "sha512-Gzbf0wUtKfyPaqf0Plz+Ctinf9eQIzxEqBHwSvbGfeOm9GMNdLxyu1dNiCUfM+x6r4BE0xUJNh3Nmg9gfAtTmg==",
|
||||
"dev": true
|
||||
},
|
||||
"elliptic": {
|
||||
"version": "6.5.4",
|
||||
@@ -17418,7 +17421,8 @@
|
||||
"node-releases": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz",
|
||||
"integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA=="
|
||||
"integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==",
|
||||
"dev": true
|
||||
},
|
||||
"normalize-path": {
|
||||
"version": "3.0.0",
|
||||
@@ -20097,18 +20101,18 @@
|
||||
"dev": true
|
||||
},
|
||||
"webpack": {
|
||||
"version": "5.89.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz",
|
||||
"integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==",
|
||||
"version": "5.90.1",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.1.tgz",
|
||||
"integrity": "sha512-SstPdlAC5IvgFnhiRok8hqJo/+ArAbNv7rhU4fnWGHNVfN59HSQFaxZDSAL3IFG2YmqxuRs+IU33milSxbPlog==",
|
||||
"requires": {
|
||||
"@types/eslint-scope": "^3.7.3",
|
||||
"@types/estree": "^1.0.0",
|
||||
"@types/estree": "^1.0.5",
|
||||
"@webassemblyjs/ast": "^1.11.5",
|
||||
"@webassemblyjs/wasm-edit": "^1.11.5",
|
||||
"@webassemblyjs/wasm-parser": "^1.11.5",
|
||||
"acorn": "^8.7.1",
|
||||
"acorn-import-assertions": "^1.9.0",
|
||||
"browserslist": "^4.14.5",
|
||||
"browserslist": "^4.21.10",
|
||||
"chrome-trace-event": "^1.0.2",
|
||||
"enhanced-resolve": "^5.15.0",
|
||||
"es-module-lexer": "^1.2.1",
|
||||
@@ -20122,15 +20126,15 @@
|
||||
"neo-async": "^2.6.2",
|
||||
"schema-utils": "^3.2.0",
|
||||
"tapable": "^2.1.1",
|
||||
"terser-webpack-plugin": "^5.3.7",
|
||||
"terser-webpack-plugin": "^5.3.10",
|
||||
"watchpack": "^2.4.0",
|
||||
"webpack-sources": "^3.2.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
|
||||
"integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA=="
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="
|
||||
},
|
||||
"@jridgewell/sourcemap-codec": {
|
||||
"version": "1.4.15",
|
||||
@@ -20138,9 +20142,9 @@
|
||||
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
|
||||
},
|
||||
"@jridgewell/trace-mapping": {
|
||||
"version": "0.3.20",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz",
|
||||
"integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==",
|
||||
"version": "0.3.22",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz",
|
||||
"integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==",
|
||||
"requires": {
|
||||
"@jridgewell/resolve-uri": "^3.1.0",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
@@ -20151,16 +20155,42 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="
|
||||
},
|
||||
"browserslist": {
|
||||
"version": "4.23.0",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz",
|
||||
"integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==",
|
||||
"requires": {
|
||||
"caniuse-lite": "^1.0.30001587",
|
||||
"electron-to-chromium": "^1.4.668",
|
||||
"node-releases": "^2.0.14",
|
||||
"update-browserslist-db": "^1.0.13"
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001587",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz",
|
||||
"integrity": "sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA=="
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.4.670",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.670.tgz",
|
||||
"integrity": "sha512-hcijYOWjOtjKrKPtNA6tuLlA/bTLO3heFG8pQA6mLpq7dRydSWicXova5lyxDzp1iVJaYhK7J2OQlGE52KYn7A=="
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
|
||||
},
|
||||
"node-releases": {
|
||||
"version": "2.0.14",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
|
||||
"integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw=="
|
||||
},
|
||||
"schema-utils": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
|
||||
@@ -20172,17 +20202,17 @@
|
||||
}
|
||||
},
|
||||
"serialize-javascript": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz",
|
||||
"integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==",
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
|
||||
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
|
||||
"requires": {
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"terser": {
|
||||
"version": "5.26.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.26.0.tgz",
|
||||
"integrity": "sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==",
|
||||
"version": "5.27.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.27.0.tgz",
|
||||
"integrity": "sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==",
|
||||
"requires": {
|
||||
"@jridgewell/source-map": "^0.3.3",
|
||||
"acorn": "^8.8.2",
|
||||
@@ -20202,6 +20232,15 @@
|
||||
"terser": "^5.26.0"
|
||||
}
|
||||
},
|
||||
"update-browserslist-db": {
|
||||
"version": "1.0.13",
|
||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
|
||||
"integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==",
|
||||
"requires": {
|
||||
"escalade": "^3.1.1",
|
||||
"picocolors": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"webpack-sources": {
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
|
||||
|
||||
+3
-3
@@ -33,13 +33,13 @@
|
||||
"acorn-import-assertions": "^1.9.0",
|
||||
"admin-lte": "^2.4.18",
|
||||
"ajv": "^6.12.6",
|
||||
"alpinejs": "^3.13.3",
|
||||
"alpinejs": "^3.13.5",
|
||||
"blueimp-file-upload": "^9.34.0",
|
||||
"bootstrap": "^3.4.1",
|
||||
"bootstrap-colorpicker": "^2.5.3",
|
||||
"bootstrap-datepicker": "^1.10.0",
|
||||
"bootstrap-less": "^3.3.8",
|
||||
"bootstrap-table": "1.22.1",
|
||||
"bootstrap-table": "1.22.2",
|
||||
"chart.js": "^2.9.4",
|
||||
"clipboard": "^2.0.11",
|
||||
"css-loader": "^5.0.0",
|
||||
@@ -59,6 +59,6 @@
|
||||
"tableexport.jquery.plugin": "1.28.0",
|
||||
"tether": "^1.4.0",
|
||||
"vue-resource": "^1.5.2",
|
||||
"webpack": "^5.89.0"
|
||||
"webpack": "^5.90.0"
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"/js/build/app.js": "/js/build/app.js?id=72071a8a4dc754c61b0440d3c4119cbf",
|
||||
"/js/build/app.js": "/js/build/app.js?id=cad71122a8a3f0cd6c5960e95f4f0f8a",
|
||||
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=392cc93cfc0be0349bab9697669dd091",
|
||||
"/css/build/overrides.css": "/css/build/overrides.css?id=6a7f37afafaaf9ccea99a7391cdf02b2",
|
||||
"/css/build/app.css": "/css/build/app.css?id=ea3875faceb1d09c162d00fbf5b4df57",
|
||||
@@ -18,7 +18,7 @@
|
||||
"/css/dist/skins/skin-green.css": "/css/dist/skins/skin-green.css?id=b48f4d8af0e1ca5621c161e93951109f",
|
||||
"/css/dist/skins/skin-contrast.css": "/css/dist/skins/skin-contrast.css?id=f0fbbb0ac729ea092578fb05ca615460",
|
||||
"/css/dist/skins/skin-red.css": "/css/dist/skins/skin-red.css?id=b9a74ec0cd68f83e7480d5ae39919beb",
|
||||
"/css/dist/all.css": "/css/dist/all.css?id=4c76e55563c6761a252a7df48c5d9d66",
|
||||
"/css/dist/all.css": "/css/dist/all.css?id=2ef1965d45a0a72336dd8e9b93f82d80",
|
||||
"/css/dist/signature-pad.css": "/css/dist/signature-pad.css?id=6a89d3cd901305e66ced1cf5f13147f7",
|
||||
"/css/dist/signature-pad.min.css": "/css/dist/signature-pad.min.css?id=6a89d3cd901305e66ced1cf5f13147f7",
|
||||
"/css/webfonts/fa-brands-400.ttf": "/css/webfonts/fa-brands-400.ttf?id=69e5d8e4e818f05fd882cceb758d1eba",
|
||||
@@ -29,11 +29,11 @@
|
||||
"/css/webfonts/fa-solid-900.woff2": "/css/webfonts/fa-solid-900.woff2?id=a0feb384c3c6071947a49708f2b0bc85",
|
||||
"/css/webfonts/fa-v4compatibility.ttf": "/css/webfonts/fa-v4compatibility.ttf?id=e24ec0b8661f7fa333b29444df39e399",
|
||||
"/css/webfonts/fa-v4compatibility.woff2": "/css/webfonts/fa-v4compatibility.woff2?id=e11465c0eff0549edd4e8ea6bbcf242f",
|
||||
"/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=2bd29fa7f9d666800c246a52ce708633",
|
||||
"/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=afa255bf30b2a7c11a97e3165128d183",
|
||||
"/js/build/vendor.js": "/js/build/vendor.js?id=a2b971da417306a63385c8098acfe4af",
|
||||
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=1f678160a05960c3087fb8263168ff41",
|
||||
"/js/dist/all.js": "/js/dist/all.js?id=256c2e7da22a51ce49b03ffa24527cee",
|
||||
"/js/dist/all-defer.js": "/js/dist/all-defer.js?id=7f9a130eda6916eaa32a0a57e81918f3",
|
||||
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=29340c70d13855fa0165cd4d799c6f5b",
|
||||
"/js/dist/all.js": "/js/dist/all.js?id=a9bde3f908f73634c0d1b4cd3f835092",
|
||||
"/js/dist/all-defer.js": "/js/dist/all-defer.js?id=19ccc62a8f1ea103dede4808837384d4",
|
||||
"/css/dist/skins/skin-green.min.css": "/css/dist/skins/skin-green.min.css?id=b48f4d8af0e1ca5621c161e93951109f",
|
||||
"/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=0ed42b67f9b02a74815e885bfd9e3f66",
|
||||
"/css/dist/skins/skin-black.min.css": "/css/dist/skins/skin-black.min.css?id=1f33ca3d860461c1127ec465ab3ebb6b",
|
||||
|
||||
@@ -191,17 +191,12 @@ $(document).ready(function () {
|
||||
* Select2
|
||||
*/
|
||||
|
||||
var iOS = /iPhone|iPad|iPod/.test(navigator.userAgent) && !window.MSStream;
|
||||
if(!iOS)
|
||||
{
|
||||
// Vue collision: Avoid overriding a vue select2 instance
|
||||
// by checking to see if the item has already been select2'd.
|
||||
$('select.select2:not(".select2-hidden-accessible")').each(function (i,obj) {
|
||||
{
|
||||
$(obj).select2();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// $('.datepicker').datepicker();
|
||||
// var datepicker = $.fn.datepicker.noConflict(); // return $.fn.datepicker to previously assigned value
|
||||
|
||||
@@ -67,9 +67,10 @@ return [
|
||||
'footer_text' => 'Additional Footer Text ',
|
||||
'footer_text_help' => 'This text will appear in the right-side footer. Links are allowed using <a href="https://help.github.com/articles/github-flavored-markdown/">Github flavored markdown</a>. Line breaks, headers, images, etc may result in unpredictable results.',
|
||||
'general_settings' => 'General Settings',
|
||||
'general_settings_keywords' => 'company support, signature, acceptance, email format, username format, images, per page, thumbnail, eula, tos, dashboard, privacy',
|
||||
'general_settings_keywords' => 'company support, signature, acceptance, email format, username format, images, per page, thumbnail, eula, gravatar, tos, dashboard, privacy',
|
||||
'general_settings_help' => 'Default EULA and more',
|
||||
'generate_backup' => 'Generate Backup',
|
||||
'google_workspaces' => 'Google Workspaces',
|
||||
'header_color' => 'Header Color',
|
||||
'info' => 'These settings let you customize certain aspects of your installation.',
|
||||
'label_logo' => 'Label Logo',
|
||||
@@ -86,7 +87,6 @@ return [
|
||||
'ldap_integration' => 'LDAP Integration',
|
||||
'ldap_settings' => 'LDAP Settings',
|
||||
'ldap_client_tls_cert_help' => 'Client-Side TLS Certificate and Key for LDAP connections are usually only useful in Google Workspace configurations with "Secure LDAP." Both are required.',
|
||||
'ldap_client_tls_key' => 'LDAP Client-Side TLS key',
|
||||
'ldap_location' => 'LDAP Location',
|
||||
'ldap_location_help' => 'The Ldap Location field should be used if <strong>an OU is not being used in the Base Bind DN.</strong> Leave this blank if an OU search is being used.',
|
||||
'ldap_login_test_help' => 'Enter a valid LDAP username and password from the base DN you specified above to test whether your LDAP login is configured correctly. YOU MUST SAVE YOUR UPDATED LDAP SETTINGS FIRST.',
|
||||
@@ -121,8 +121,8 @@ return [
|
||||
'ldap_test' => 'Test LDAP',
|
||||
'ldap_test_sync' => 'Test LDAP Synchronization',
|
||||
'license' => 'Software License',
|
||||
'load_remote_text' => 'Remote Scripts',
|
||||
'load_remote_help_text' => 'This Snipe-IT install can load scripts from the outside world.',
|
||||
'load_remote' => 'Use Gravatar',
|
||||
'load_remote_help_text' => 'Uncheck this box if your install cannot load scripts from the outside internet. This will prevent Snipe-IT from trying load images from Gravatar.',
|
||||
'login' => 'Login Attempts',
|
||||
'login_attempt' => 'Login Attempt',
|
||||
'login_ip' => 'IP Address',
|
||||
|
||||
@@ -459,6 +459,7 @@ return [
|
||||
'no_autoassign_licenses_help' => 'Do not include user for bulk-assigning through the license UI or cli tools.',
|
||||
'modal_confirm_generic' => 'Are you sure?',
|
||||
'cannot_be_deleted' => 'This item cannot be deleted',
|
||||
'cannot_be_edited' => 'This item cannot be edited.',
|
||||
'undeployable_tooltip' => 'This item cannot be checked out. Check the quantity remaining.',
|
||||
'serial_number' => 'Serial Number',
|
||||
'item_notes' => ':item Notes',
|
||||
@@ -501,5 +502,6 @@ return [
|
||||
'action_source' => 'Action Source',
|
||||
'or' => 'or',
|
||||
'url' => 'URL',
|
||||
'edit_fieldset' => 'Edit fieldset fields and options',
|
||||
|
||||
];
|
||||
|
||||
@@ -42,6 +42,7 @@ return [
|
||||
'checkin_date' => 'Checkin Date:',
|
||||
'checkout_date' => 'Checkout Date:',
|
||||
'checkedout_from' => 'Checked out from',
|
||||
'checkedin_from' => 'Checked in from',
|
||||
'checked_into' => 'Checked into',
|
||||
'click_on_the_link_accessory' => 'Please click on the link at the bottom to confirm that you have received the accessory.',
|
||||
'click_on_the_link_asset' => 'Please click on the link at the bottom to confirm that you have received the asset.',
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<i class="fas fa-barcode" aria-hidden="true"></i>
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">{{ trans('general.assets') }}
|
||||
{!! (($company->assets) && ($company->assets()->AssetsForShow()->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($company->assets()->AssetsForShow()->count()).'</badge>' : '' !!}
|
||||
{!! ($company->assets()->AssetsForShow()->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($company->assets()->AssetsForShow()->count()).'</badge>' : '' !!}
|
||||
|
||||
</span>
|
||||
</a>
|
||||
@@ -33,7 +33,7 @@
|
||||
<i class="far fa-save"></i>
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">{{ trans('general.licenses') }}
|
||||
{!! (($company->licenses) && ($company->licenses->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($company->licenses->count()).'</badge>' : '' !!}
|
||||
{!! ($company->licenses->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($company->licenses->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
@@ -43,7 +43,7 @@
|
||||
<span class="hidden-lg hidden-md">
|
||||
<i class="far fa-keyboard"></i>
|
||||
</span> <span class="hidden-xs hidden-sm">{{ trans('general.accessories') }}
|
||||
{!! (($company->accessories) && ($company->accessories->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($company->accessories->count()).'</badge>' : '' !!}
|
||||
{!! ($company->accessories->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($company->accessories->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
@@ -53,7 +53,7 @@
|
||||
<span class="hidden-lg hidden-md">
|
||||
<i class="fas fa-tint"></i></span>
|
||||
<span class="hidden-xs hidden-sm">{{ trans('general.consumables') }}
|
||||
{!! (($company->consumables) && ($company->consumables->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($company->consumables->count()).'</badge>' : '' !!}
|
||||
{!! ($company->consumables->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($company->consumables->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -279,7 +279,7 @@
|
||||
</strong>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
{!! nl2br(e($component->notes)) !!}
|
||||
{!! nl2br(Helper::parseEscapedMarkedownInline($component->notes)) !!}
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
@can('update', $custom_fieldset)
|
||||
<form method="post" action="{{ route('fields.disassociate', [$field, $custom_fieldset->id]) }}">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-sm btn-danger">{{ trans('button.remove') }}</button>
|
||||
<button type="submit" class="btn btn-sm btn-danger"><i class="fa fa-trash icon-white" aria-hidden="true"></i></button>
|
||||
</form>
|
||||
@endcan
|
||||
</td>
|
||||
@@ -90,35 +90,34 @@
|
||||
<td colspan="8">
|
||||
{{ Form::open(['route' =>
|
||||
["fieldsets.associate",$custom_fieldset->id],
|
||||
'class'=>'form-horizontal',
|
||||
'class'=>'form-inline',
|
||||
'id' => 'ordering']) }}
|
||||
|
||||
|
||||
<div class="form-group col-md-4">
|
||||
<div class="form-group">
|
||||
<label for="field_id" class="sr-only">
|
||||
{{ trans('admin/custom-field/general.add_field_to_fieldset')}}
|
||||
</label>
|
||||
{{ Form::select("field_id",$custom_fields_list,"",['aria-label'=>'field_id', 'class'=>'select2']) }}
|
||||
{{ Form::select("field_id",$custom_fields_list,"",['aria-label'=>'field_id', 'class'=>'select2', 'style' => 'min-width:400px;']) }}
|
||||
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-2" style="vertical-align: middle;">
|
||||
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('required', 'on', old('required'), array('aria-label'=>'required')) }}
|
||||
{{ trans('admin/custom_fields/general.required') }}
|
||||
</label>
|
||||
|
||||
</div>
|
||||
<div class="form-group col-md-2" style="display: none;">
|
||||
|
||||
{{ Form::text('order', $maxid, array('class' => 'form-control col-sm-1 col-md-1', 'style'=> 'width: 80px; padding-;right: 10px;', 'aria-label'=>'order', 'maxlength'=>'3', 'size'=>'3')) }}
|
||||
<div class="form-group" style="display: none;">
|
||||
{{ Form::text('order', $maxid, array('aria-label'=>'order', 'maxlength'=>'3', 'size'=>'3')) }}
|
||||
<label for="order">{{ trans('admin/custom_fields/general.order') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-3">
|
||||
<button type="submit" class="btn btn-primary"> {{ trans('general.save') }}</button>
|
||||
<div class="checkbox-inline">
|
||||
<label>
|
||||
{{ Form::checkbox('required', 'on', old('required')) }}
|
||||
<span style="padding-left: 10px;">{{ trans('admin/custom_fields/general.required') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<span style="padding-left: 10px;">
|
||||
<button type="submit" class="btn btn-primary"> {{ trans('general.save') }}</button>
|
||||
</span>
|
||||
|
||||
{{ Form::close() }}
|
||||
|
||||
</td>
|
||||
|
||||
@@ -73,7 +73,14 @@
|
||||
<nobr>
|
||||
|
||||
@can('update', $fieldset)
|
||||
<a href="{{ route('fieldsets.edit', $fieldset->id) }}" class="btn btn-warning btn-sm">
|
||||
|
||||
<a href="{{ route('fieldsets.show', ['fieldset' => $fieldset->id]) }}" data-tooltip="true" title="{{ trans('general.edit_fieldset') }}">
|
||||
<button type="submit" class="btn btn-info btn-sm">
|
||||
<i class="fa-regular fa-rectangle-list"></i>
|
||||
</button>
|
||||
</a>
|
||||
|
||||
<a href="{{ route('fieldsets.edit', $fieldset->id) }}" class="btn btn-warning btn-sm" data-tooltip="true" title="{{ trans('general.update') }}">
|
||||
<i class="fas fa-pencil-alt" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('button.edit') }}</span>
|
||||
</a>
|
||||
@@ -82,9 +89,9 @@
|
||||
@can('delete', $fieldset)
|
||||
{{ Form::open(['route' => array('fieldsets.destroy', $fieldset->id), 'method' => 'delete','style' => 'display:inline-block']) }}
|
||||
@if($fieldset->models->count() > 0)
|
||||
<button type="submit" class="btn btn-danger btn-sm disabled" disabled><i class="fas fa-trash"></i></button>
|
||||
<button type="submit" class="btn btn-danger btn-sm disabled" data-tooltip="true" title="{{ trans('general.cannot_be_deleted') }}" disabled><i class="fas fa-trash"></i></button>
|
||||
@else
|
||||
<button type="submit" class="btn btn-danger btn-sm"><i class="fas fa-trash"></i></button>
|
||||
<button type="submit" class="btn btn-danger btn-sm" data-tooltip="true" title="{{ trans('general.delete') }}"><i class="fas fa-trash"></i></button>
|
||||
@endif
|
||||
{{ Form::close() }}
|
||||
@endcan
|
||||
@@ -188,7 +195,7 @@
|
||||
<nobr>
|
||||
{{ Form::open(array('route' => array('fields.destroy', $field->id), 'method' => 'delete', 'style' => 'display:inline-block')) }}
|
||||
@can('update', $field)
|
||||
<a href="{{ route('fields.edit', $field->id) }}" class="btn btn-warning btn-sm">
|
||||
<a href="{{ route('fields.edit', $field->id) }}" class="btn btn-warning btn-sm" data-tooltip="true" title="{{ trans('general.update') }}">
|
||||
<i class="fas fa-pencil-alt" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('button.edit') }}</span>
|
||||
</a>
|
||||
@@ -197,11 +204,11 @@
|
||||
@can('delete', $field)
|
||||
|
||||
@if($field->fieldset->count()>0)
|
||||
<button type="submit" class="btn btn-danger btn-sm disabled" disabled>
|
||||
<button type="submit" class="btn btn-danger btn-sm disabled" data-tooltip="true" title="{{ trans('general.cannot_be_deleted') }}" disabled>
|
||||
<i class="fas fa-trash" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('button.delete') }}</span></button>
|
||||
@else
|
||||
<button type="submit" class="btn btn-danger btn-sm">
|
||||
<button type="submit" class="btn btn-danger btn-sm" data-tooltip="true" title="{{ trans('general.delete') }}">
|
||||
<i class="fas fa-trash" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('button.delete') }}</span>
|
||||
</button>
|
||||
|
||||
@@ -872,11 +872,13 @@
|
||||
|
||||
|
||||
@can('update', $asset)
|
||||
@if ($asset->deleted_at=='')
|
||||
<div class="col-md-12" style="padding-top: 5px;">
|
||||
<a href="{{ route('hardware.edit', $asset->id) }}" style="width: 100%;" class="btn btn-sm btn-primary hidden-print">
|
||||
{{ trans('admin/hardware/general.edit') }}
|
||||
</a>
|
||||
</div>
|
||||
@endif
|
||||
@endcan
|
||||
|
||||
@can('create', $asset)
|
||||
|
||||
@@ -140,17 +140,15 @@
|
||||
<div class="navbar-custom-menu">
|
||||
<ul class="nav navbar-nav">
|
||||
@can('index', \App\Models\Asset::class)
|
||||
<li aria-hidden="true"
|
||||
{!! (Request::is('hardware*') ? ' class="active"' : '') !!} tabindex="-1">
|
||||
<li aria-hidden="true"{!! (Request::is('hardware*') ? ' class="active"' : '') !!}>
|
||||
<a href="{{ url('hardware') }}" accesskey="1" tabindex="-1">
|
||||
<i class="fas fa-barcode fa-fw" aria-hidden="true"></i>
|
||||
<i class="fas fa-barcode fa-fw"></i>
|
||||
<span class="sr-only">{{ trans('general.assets') }}</span>
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
@can('view', \App\Models\License::class)
|
||||
<li aria-hidden="true"
|
||||
{!! (Request::is('licenses*') ? ' class="active"' : '') !!} tabindex="-1">
|
||||
<li aria-hidden="true"{!! (Request::is('licenses*') ? ' class="active"' : '') !!}>
|
||||
<a href="{{ route('licenses.index') }}" accesskey="2" tabindex="-1">
|
||||
<i class="far fa-save fa-fw"></i>
|
||||
<span class="sr-only">{{ trans('general.licenses') }}</span>
|
||||
@@ -158,8 +156,7 @@
|
||||
</li>
|
||||
@endcan
|
||||
@can('index', \App\Models\Accessory::class)
|
||||
<li aria-hidden="true"
|
||||
{!! (Request::is('accessories*') ? ' class="active"' : '') !!} tabindex="-1">
|
||||
<li aria-hidden="true"{!! (Request::is('accessories*') ? ' class="active"' : '') !!}>
|
||||
<a href="{{ route('accessories.index') }}" accesskey="3" tabindex="-1">
|
||||
<i class="far fa-keyboard fa-fw"></i>
|
||||
<span class="sr-only">{{ trans('general.accessories') }}</span>
|
||||
@@ -233,7 +230,8 @@
|
||||
<li {!! (Request::is('accessories/create') ? 'class="active"' : '') !!}>
|
||||
<a href="{{ route('accessories.create') }}" tabindex="-1">
|
||||
<i class="far fa-keyboard fa-fw" aria-hidden="true"></i>
|
||||
{{ trans('general.accessory') }}</a>
|
||||
{{ trans('general.accessory') }}
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
@can('create', \App\Models\Consumable::class)
|
||||
@@ -982,7 +980,7 @@
|
||||
container: 'body',
|
||||
animation: true,
|
||||
});
|
||||
|
||||
|
||||
$('[data-toggle="popover"]').popover();
|
||||
$('.select2 span').addClass('needsclick');
|
||||
$('.select2 span').removeAttr('title');
|
||||
|
||||
@@ -133,8 +133,10 @@
|
||||
<i class="fa-solid fa-list-check" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.import') }}</span>
|
||||
</button>
|
||||
<a href="#" wire:click="$set('activeFile',null)">
|
||||
<button class="btn btn-sm btn-danger" wire:click="destroy({{ $currentFile->id }})">
|
||||
<i class="fas fa-trash icon-white" aria-hidden="true"></i><span class="sr-only"></span></button>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
@@ -61,9 +61,9 @@
|
||||
<div class="col-md-9 required" wire:ignore>
|
||||
|
||||
@if (Helper::isDemoMode())
|
||||
{{ Form::select('webhook_selected', array('slack' => trans('admin/settings/general.slack'), 'general' => trans('admin/settings/general.general_webhook'), 'microsoft' => trans('admin/settings/general.ms_teams')), old('webhook_selected', $webhook_selected), array('class'=>'select2 form-control', 'aria-label' => 'webhook_selected', 'id' => 'select2', 'style'=>'width:100%', 'disabled')) }}
|
||||
{{ Form::select('webhook_selected', array('slack' => trans('admin/settings/general.slack'), 'general' => trans('admin/settings/general.general_webhook'),'google' => trans('admin/settings/general.google_workspaces'), 'microsoft' => trans('admin/settings/general.ms_teams')), old('webhook_selected', $webhook_selected), array('class'=>'select2 form-control', 'aria-label' => 'webhook_selected', 'id' => 'select2', 'style'=>'width:100%', 'disabled')) }}
|
||||
@else
|
||||
{{ Form::select('webhook_selected', array('slack' => trans('admin/settings/general.slack'), 'general' => trans('admin/settings/general.general_webhook'), 'microsoft' => trans('admin/settings/general.ms_teams')), old('webhook_selected', $webhook_selected), array('class'=>'select2 form-control', 'aria-label' => 'webhook_selected', 'id' => 'select2', 'data-minimum-results-for-search' => '-1', 'style'=>'width:100%')) }}
|
||||
{{ Form::select('webhook_selected', array('slack' => trans('admin/settings/general.slack'), 'general' => trans('admin/settings/general.general_webhook'),'google' => trans('admin/settings/general.google_workspaces'), 'microsoft' => trans('admin/settings/general.ms_teams')), old('webhook_selected', $webhook_selected), array('class'=>'select2 form-control', 'aria-label' => 'webhook_selected', 'id' => 'select2', 'data-minimum-results-for-search' => '-1', 'style'=>'width:100%')) }}
|
||||
@endif
|
||||
|
||||
</div>
|
||||
@@ -90,23 +90,25 @@
|
||||
|
||||
|
||||
<!-- Webhook channel -->
|
||||
<div class="form-group{{ $errors->has('webhook_channel') ? ' error' : '' }}">
|
||||
<div class="col-md-2">
|
||||
{{ Form::label('webhook_channel', trans('admin/settings/general.webhook_channel',['app' => $webhook_name ])) }}
|
||||
</div>
|
||||
<div class="col-md-9 required">
|
||||
<input type="text" wire:model.lazy="webhook_channel" class="form-control" placeholder="#IT-Ops" value="{{ old('webhook_channel', $webhook_channel) }}"{{ Helper::isDemoMode() ? ' disabled' : ''}}>
|
||||
@if($webhook_selected != 'microsoft' && $webhook_selected!= 'google')
|
||||
<div class="form-group{{ $errors->has('webhook_channel') ? ' error' : '' }}">
|
||||
<div class="col-md-2">
|
||||
{{ Form::label('webhook_channel', trans('admin/settings/general.webhook_channel',['app' => $webhook_name ])) }}
|
||||
</div>
|
||||
<div class="col-md-9 required">
|
||||
<input type="text" wire:model.lazy="webhook_channel" class="form-control" placeholder="#IT-Ops" value="{{ old('webhook_channel', $webhook_channel) }}"{{ Helper::isDemoMode() ? ' disabled' : ''}}>
|
||||
|
||||
{!! $errors->first('webhook_channel', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
{!! $errors->first('webhook_channel', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Helper::isDemoMode())
|
||||
@include('partials.forms.demo-mode')
|
||||
@endif
|
||||
|
||||
<!-- Webhook botname -->
|
||||
@if($webhook_selected != 'microsoft')
|
||||
@if($webhook_selected != 'microsoft' && $webhook_selected != 'google')
|
||||
<div class="form-group{{ $errors->has('webhook_botname') ? ' error' : '' }}">
|
||||
<div class="col-md-2">
|
||||
{{ Form::label('webhook_botname', trans('admin/settings/general.webhook_botname',['app' => $webhook_name ])) }}
|
||||
@@ -122,14 +124,11 @@
|
||||
@endif
|
||||
|
||||
<!--Webhook Integration Test-->
|
||||
|
||||
@if($webhook_endpoint != null && $webhook_channel != null)
|
||||
<div class="form-group">
|
||||
<div class="col-md-offset-2 col-md-9">
|
||||
@if($webhook_selected == "microsoft")
|
||||
<a href="#" wire:click.prevent="msTeamTestWebhook"
|
||||
@else
|
||||
<a href="#" wire:click.prevent="testWebhook"
|
||||
@endif
|
||||
<a href="#" wire:click.prevent="{{$webhook_test}}"
|
||||
class="btn btn-default btn-sm pull-left">
|
||||
<i class="{{$webhook_icon}}" aria-hidden="true"></i>
|
||||
{!! trans('admin/settings/general.webhook_test',['app' => ucwords($webhook_selected) ]) !!}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('general.users') }}
|
||||
{!! (($location->users) && ($location->users->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($location->users->count()).'</badge>' : '' !!}
|
||||
{!! ($location->users->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($location->users->count()).'</badge>' : '' !!}
|
||||
|
||||
</span>
|
||||
</a>
|
||||
@@ -38,7 +38,7 @@
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('admin/locations/message.current_location') }}
|
||||
{!! (($location->assets) && ($location->assets()->AssetsForShow()->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($location->assets()->AssetsForShow()->count()).'</badge>' : '' !!}
|
||||
{!! ($location->assets()->AssetsForShow()->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($location->assets()->AssetsForShow()->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
@@ -51,7 +51,7 @@
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('admin/hardware/form.default_location') }}
|
||||
{!! (($location->rtd_assets) && ($location->rtd_assets()->AssetsForShow()->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($location->rtd_assets()->AssetsForShow()->count()).'</badge>' : '' !!}
|
||||
{!! ($location->rtd_assets()->AssetsForShow()->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($location->rtd_assets()->AssetsForShow()->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
@@ -63,7 +63,7 @@
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('admin/locations/message.assigned_assets') }}
|
||||
{!! (($location->rtd_assets) && ($location->assignedAssets()->AssetsForShow()->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($location->assignedAssets()->AssetsForShow()->count()).'</badge>' : '' !!}
|
||||
{!! ($location->assignedAssets()->AssetsForShow()->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($location->assignedAssets()->AssetsForShow()->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
@@ -76,7 +76,7 @@
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('general.accessories') }}
|
||||
{!! (($location->accessories) && ($location->accessories->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($location->accessories->count()).'</badge>' : '' !!}
|
||||
{!! ($location->accessories->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($location->accessories->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
@@ -88,7 +88,7 @@
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('general.consumables') }}
|
||||
{!! (($location->consumables) && ($location->consumables->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($location->consumables->count()).'</badge>' : '' !!}
|
||||
{!! ($location->consumables->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($location->consumables->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
@@ -100,7 +100,7 @@
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('general.components') }}
|
||||
{!! (($location->components) && ($location->components->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($location->components->count()).'</badge>' : '' !!}
|
||||
{!! ($location->components->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($location->components->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('general.assets') }}
|
||||
{!! (($manufacturer->assets) && ($manufacturer->assets()->AssetsForShow()->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($manufacturer->assets()->AssetsForShow()->count()).'</badge>' : '' !!}
|
||||
{!! ($manufacturer->assets()->AssetsForShow()->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($manufacturer->assets()->AssetsForShow()->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
|
||||
</a>
|
||||
@@ -55,7 +55,7 @@
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('general.licenses') }}
|
||||
{!! (($manufacturer->licenses) && ($manufacturer->licenses->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($manufacturer->licenses->count()).'</badge>' : '' !!}
|
||||
{!! ($manufacturer->licenses->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($manufacturer->licenses->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
|
||||
</a>
|
||||
@@ -68,7 +68,7 @@
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('general.accessories') }}
|
||||
{!! (($manufacturer->accessories) && ($manufacturer->accessories->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($manufacturer->accessories->count()).'</badge>' : '' !!}
|
||||
{!! ($manufacturer->accessories->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($manufacturer->accessories->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
|
||||
</a>
|
||||
@@ -81,7 +81,7 @@
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('general.consumables') }}
|
||||
{!! (($manufacturer->consumables) && ($manufacturer->consumables->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($manufacturer->consumables->count()).'</badge>' : '' !!}
|
||||
{!! ($manufacturer->consumables->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($manufacturer->consumables->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
|
||||
</a>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('general.assets') }}
|
||||
{!! (($model->assets_count) && ($model->assets_count > 0 )) ? '<badge class="badge badge-secondary">'.number_format($model->assets_count).'</badge>' : '' !!}
|
||||
{!! ($model->assets_count > 0 ) ? '<badge class="badge badge-secondary">'.number_format($model->assets_count).'</badge>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
@@ -309,7 +309,7 @@
|
||||
@if ($model->notes)
|
||||
<li>
|
||||
{{ trans('general.notes') }}:
|
||||
{{ $model->notes }}
|
||||
{!! nl2br(Helper::parseEscapedMarkedownInline($model->notes)) !!}
|
||||
</li>
|
||||
@endif
|
||||
|
||||
|
||||
@@ -296,6 +296,10 @@
|
||||
|
||||
if ((row.available_actions) && (row.available_actions.update === true)) {
|
||||
actions += '<a href="{{ config('app.url') }}/' + dest + '/' + row.id + '/edit" class="actions btn btn-sm btn-warning" data-tooltip="true" title="{{ trans('general.update') }}"><i class="fas fa-pencil-alt" aria-hidden="true"></i><span class="sr-only">{{ trans('general.update') }}</span></a> ';
|
||||
} else {
|
||||
if ((row.available_actions) && (row.available_actions.update != true)) {
|
||||
actions += '<span data-tooltip="true" title="{{ trans('general.cannot_be_edited') }}"><a class="btn btn-warning btn-sm disabled" onClick="return false;"><i class="fas fa-pencil-alt"></i></a></span> ';
|
||||
}
|
||||
}
|
||||
|
||||
if ((row.available_actions) && (row.available_actions.delete === true)) {
|
||||
@@ -623,6 +627,9 @@
|
||||
|
||||
function assetTagLinkFormatter(value, row) {
|
||||
if ((row.asset) && (row.asset.id)) {
|
||||
if (row.asset.deleted_at!='') {
|
||||
return '<span style="white-space: nowrap;"><i class="fas fa-times text-danger"></i><span class="sr-only">deleted</span> <del><a href="{{ config('app.url') }}/hardware/' + row.asset.id + '" data-tooltip="true" title="{{ trans('admin/hardware/general.deleted') }}">' + row.asset.asset_tag + '</a></del></span>';
|
||||
}
|
||||
return '<a href="{{ config('app.url') }}/hardware/' + row.asset.id + '">' + row.asset.asset_tag + '</a>';
|
||||
}
|
||||
return '';
|
||||
@@ -640,7 +647,17 @@
|
||||
if ((row.asset) && (row.asset.name)) {
|
||||
return '<a href="{{ config('app.url') }}/hardware/' + row.asset.id + '">' + row.asset.name + '</a>';
|
||||
}
|
||||
}
|
||||
|
||||
function assetSerialLinkFormatter(value, row) {
|
||||
|
||||
if ((row.asset) && (row.asset.serial)) {
|
||||
if (row.asset.deleted_at!='') {
|
||||
return '<span style="white-space: nowrap;"><i class="fas fa-times text-danger"></i><span class="sr-only">deleted</span> <del><a href="{{ config('app.url') }}/hardware/' + row.asset.id + '" data-tooltip="true" title="{{ trans('admin/hardware/general.deleted') }}">' + row.asset.serial + '</a></del></span>';
|
||||
}
|
||||
return '<a href="{{ config('app.url') }}/hardware/' + row.asset.id + '">' + row.asset.serial + '</a>';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function trueFalseFormatter(value) {
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
{!! $errors->first('image', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</div>
|
||||
<div class="col-md-4 col-md-offset-3" aria-hidden="true">
|
||||
<img id="uploadFile-imagePreview" style="max-width: 300px; display: none;" alt="{{ trans('partials/forms/general.alt_uploaded_image_thumbnail') }}">
|
||||
<img id="uploadFile-imagePreview" style="max-width: 300px; display: none;" alt="{{ trans('general.alt_uploaded_image_thumbnail') }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -128,6 +128,25 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Load gravatar -->
|
||||
<div class="form-group {{ $errors->has('load_remote') ? 'error' : '' }}">
|
||||
<div class="col-md-3">
|
||||
<strong>{{ trans('admin/settings/general.load_remote') }}</strong>
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('load_remote', '1', old('load_remote', $setting->load_remote)) }}
|
||||
{{ trans('general.yes') }}
|
||||
{!! $errors->first('load_remote', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</label>
|
||||
|
||||
<p class="help-block">
|
||||
{{ trans('admin/settings/general.load_remote_help_text') }}
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- unique serial -->
|
||||
<div class="form-group">
|
||||
<div class="col-md-3">
|
||||
@@ -137,8 +156,9 @@
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('unique_serial', '1', Request::old('unique_serial', $setting->unique_serial),array('class' => 'minimal')) }}
|
||||
{{ trans('general.yes') }}
|
||||
{!! $errors->first('unique_serial', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</label>
|
||||
{!! $errors->first('unique_serial', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
|
||||
<p class="help-block">
|
||||
{{ trans('admin/settings/general.unique_serial_help_text') }}
|
||||
</p>
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('general.assets') }}
|
||||
{!! (($supplier->assets) && ($supplier->assets()->AssetsForShow()->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($supplier->assets()->AssetsForShow()->count()).'</badge>' : '' !!}
|
||||
{!! ($supplier->assets()->AssetsForShow()->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($supplier->assets()->AssetsForShow()->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
|
||||
</a>
|
||||
@@ -48,7 +48,7 @@
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('general.accessories') }}
|
||||
{!! (($supplier->accessories) && ($supplier->accessories->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($supplier->accessories->count()).'</badge>' : '' !!}
|
||||
{!! ($supplier->accessories->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($supplier->accessories->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
@@ -60,7 +60,7 @@
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('general.licenses') }}
|
||||
{!! (($supplier->licenses) && ($supplier->licenses->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($supplier->licenses->count()).'</badge>' : '' !!}
|
||||
{!! ($supplier->licenses->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($supplier->licenses->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
@@ -72,7 +72,7 @@
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('general.components') }}
|
||||
{!! (($supplier->components) && ($supplier->components->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($supplier->components->count()).'</badge>' : '' !!}
|
||||
{!! ($supplier->components->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($supplier->components->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
@@ -84,7 +84,7 @@
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('general.consumables') }}
|
||||
{!! (($supplier->consumables) && ($supplier->consumables->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($supplier->consumables->count()).'</badge>' : '' !!}
|
||||
{!! ($supplier->consumables->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($supplier->consumables->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
@@ -96,7 +96,7 @@
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('admin/asset_maintenances/general.asset_maintenances') }}
|
||||
{!! (($supplier->asset_maintenances) && ($supplier->asset_maintenances->count() > 0 )) ? '<badge class="badge badge-secondary">'.number_format($supplier->asset_maintenances->count()).'</badge>' : '' !!}
|
||||
{!! ($supplier->asset_maintenances->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($supplier->asset_maintenances->count()).'</badge>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -131,14 +131,13 @@
|
||||
|
||||
|
||||
$(":submit").attr("disabled", "disabled");
|
||||
$("[name='status_id']").on('select2:select', function (e) {
|
||||
if (e.params.data.id != ""){
|
||||
console.log(e.params.data.id);
|
||||
$(":submit").removeAttr("disabled");
|
||||
}
|
||||
else {
|
||||
$(":submit").attr("disabled", "disabled");
|
||||
}
|
||||
});
|
||||
$("[name='status_id']").on('select2:select', function (e) {
|
||||
if (e.params.data.id != "") {
|
||||
console.log(e.params.data.id);
|
||||
$(":submit").removeAttr("disabled");
|
||||
} else {
|
||||
$(":submit").attr("disabled", "disabled");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@stop
|
||||
@@ -0,0 +1,2 @@
|
||||
Item Name,Purchase Date,Purchase Cost,Location,Company,Order Number,Serial number,Category,Quantity
|
||||
RTX 4080,2024-01-01,5000.00,Austin,Grokability,2790,123456789,GPU,10
|
||||
|
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Accessories;
|
||||
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CheckoutAccessoryNotification;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AccessoryCheckoutTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testCheckingOutAccessoryRequiresCorrectPermission()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->create())
|
||||
->postJson(route('api.accessories.checkout', Accessory::factory()->create()))
|
||||
->assertForbidden();
|
||||
}
|
||||
|
||||
public function testValidationWhenCheckingOutAccessory()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->checkoutAccessories()->create())
|
||||
->postJson(route('api.accessories.checkout', Accessory::factory()->create()), [
|
||||
// missing assigned_to
|
||||
])
|
||||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testAccessoryMustBeAvailableWhenCheckingOut()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->checkoutAccessories()->create())
|
||||
->postJson(route('api.accessories.checkout', Accessory::factory()->withoutItemsRemaining()->create()), [
|
||||
'assigned_to' => User::factory()->create()->id,
|
||||
])
|
||||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testAccessoryCanBeCheckedOut()
|
||||
{
|
||||
$accessory = Accessory::factory()->create();
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAsForApi(User::factory()->checkoutAccessories()->create())
|
||||
->postJson(route('api.accessories.checkout', $accessory), [
|
||||
'assigned_to' => $user->id,
|
||||
]);
|
||||
|
||||
$this->assertTrue($accessory->users->contains($user));
|
||||
}
|
||||
|
||||
public function testUserSentNotificationUponCheckout()
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$accessory = Accessory::factory()->requiringAcceptance()->create();
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAsForApi(User::factory()->checkoutAccessories()->create())
|
||||
->postJson(route('api.accessories.checkout', $accessory), [
|
||||
'assigned_to' => $user->id,
|
||||
]);
|
||||
|
||||
Notification::assertSentTo($user, CheckoutAccessoryNotification::class);
|
||||
}
|
||||
|
||||
public function testActionLogCreatedUponCheckout()
|
||||
{
|
||||
$accessory = Accessory::factory()->create();
|
||||
$actor = User::factory()->checkoutAccessories()->create();
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAsForApi($actor)
|
||||
->postJson(route('api.accessories.checkout', $accessory), [
|
||||
'assigned_to' => $user->id,
|
||||
'note' => 'oh hi there',
|
||||
]);
|
||||
|
||||
$this->assertEquals(
|
||||
1,
|
||||
Actionlog::where([
|
||||
'action_type' => 'checkout',
|
||||
'target_id' => $user->id,
|
||||
'target_type' => User::class,
|
||||
'item_id' => $accessory->id,
|
||||
'item_type' => Accessory::class,
|
||||
'user_id' => $actor->id,
|
||||
'note' => 'oh hi there',
|
||||
])->count(),
|
||||
'Log entry either does not exist or there are more than expected'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Consumables;
|
||||
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CheckoutConsumableNotification;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ConsumableCheckoutTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testCheckingOutConsumableRequiresCorrectPermission()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->create())
|
||||
->postJson(route('api.consumables.checkout', Consumable::factory()->create()))
|
||||
->assertForbidden();
|
||||
}
|
||||
|
||||
public function testValidationWhenCheckingOutConsumable()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->checkoutConsumables()->create())
|
||||
->postJson(route('api.consumables.checkout', Consumable::factory()->create()), [
|
||||
// missing assigned_to
|
||||
])
|
||||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testConsumableMustBeAvailableWhenCheckingOut()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->checkoutConsumables()->create())
|
||||
->postJson(route('api.consumables.checkout', Consumable::factory()->withoutItemsRemaining()->create()), [
|
||||
'assigned_to' => User::factory()->create()->id,
|
||||
])
|
||||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testConsumableCanBeCheckedOut()
|
||||
{
|
||||
$consumable = Consumable::factory()->create();
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAsForApi(User::factory()->checkoutConsumables()->create())
|
||||
->postJson(route('api.consumables.checkout', $consumable), [
|
||||
'assigned_to' => $user->id,
|
||||
]);
|
||||
|
||||
$this->assertTrue($user->consumables->contains($consumable));
|
||||
}
|
||||
|
||||
public function testUserSentNotificationUponCheckout()
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$consumable = Consumable::factory()->requiringAcceptance()->create();
|
||||
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAsForApi(User::factory()->checkoutConsumables()->create())
|
||||
->postJson(route('api.consumables.checkout', $consumable), [
|
||||
'assigned_to' => $user->id,
|
||||
]);
|
||||
|
||||
Notification::assertSentTo($user, CheckoutConsumableNotification::class);
|
||||
}
|
||||
|
||||
public function testActionLogCreatedUponCheckout()
|
||||
{$consumable = Consumable::factory()->create();
|
||||
$actor = User::factory()->checkoutConsumables()->create();
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAsForApi($actor)
|
||||
->postJson(route('api.consumables.checkout', $consumable), [
|
||||
'assigned_to' => $user->id,
|
||||
'note' => 'oh hi there',
|
||||
]);
|
||||
|
||||
$this->assertEquals(
|
||||
1,
|
||||
Actionlog::where([
|
||||
'action_type' => 'checkout',
|
||||
'target_id' => $user->id,
|
||||
'target_type' => User::class,
|
||||
'item_id' => $consumable->id,
|
||||
'item_type' => Consumable::class,
|
||||
'user_id' => $actor->id,
|
||||
'note' => 'oh hi there',
|
||||
])->count(),
|
||||
'Log entry either does not exist or there are more than expected'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Checkins;
|
||||
|
||||
use App\Events\CheckoutableCheckedIn;
|
||||
use App\Models\Accessory;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CheckinAccessoryNotification;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AccessoryCheckinTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testCheckingInAccessoryRequiresCorrectPermission()
|
||||
{
|
||||
$accessory = Accessory::factory()->checkedOutToUser()->create();
|
||||
|
||||
$this->actingAs(User::factory()->create())
|
||||
->post(route('accessories.checkin.store', $accessory->users->first()->pivot->id))
|
||||
->assertForbidden();
|
||||
}
|
||||
|
||||
public function testAccessoryCanBeCheckedIn()
|
||||
{
|
||||
Event::fake([CheckoutableCheckedIn::class]);
|
||||
|
||||
$user = User::factory()->create();
|
||||
$accessory = Accessory::factory()->checkedOutToUser($user)->create();
|
||||
|
||||
$this->assertTrue($accessory->users->contains($user));
|
||||
|
||||
$this->actingAs(User::factory()->checkinAccessories()->create())
|
||||
->post(route('accessories.checkin.store', $accessory->users->first()->pivot->id));
|
||||
|
||||
$this->assertFalse($accessory->fresh()->users->contains($user));
|
||||
|
||||
Event::assertDispatched(CheckoutableCheckedIn::class, 1);
|
||||
}
|
||||
|
||||
public function testEmailSentToUserIfSettingEnabled()
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$user = User::factory()->create();
|
||||
$accessory = Accessory::factory()->checkedOutToUser($user)->create();
|
||||
|
||||
$accessory->category->update(['checkin_email' => true]);
|
||||
|
||||
event(new CheckoutableCheckedIn(
|
||||
$accessory,
|
||||
$user,
|
||||
User::factory()->checkinAccessories()->create(),
|
||||
'',
|
||||
));
|
||||
|
||||
Notification::assertSentTo(
|
||||
[$user],
|
||||
function (CheckinAccessoryNotification $notification, $channels) {
|
||||
return in_array('mail', $channels);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
public function testEmailNotSentToUserIfSettingDisabled()
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$user = User::factory()->create();
|
||||
$accessory = Accessory::factory()->checkedOutToUser($user)->create();
|
||||
|
||||
$accessory->category->update(['checkin_email' => false]);
|
||||
|
||||
event(new CheckoutableCheckedIn(
|
||||
$accessory,
|
||||
$user,
|
||||
User::factory()->checkinAccessories()->create(),
|
||||
'',
|
||||
));
|
||||
|
||||
Notification::assertNotSentTo(
|
||||
[$user],
|
||||
function (CheckinAccessoryNotification $notification, $channels) {
|
||||
return in_array('mail', $channels);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Checkouts;
|
||||
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CheckoutAccessoryNotification;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AccessoryCheckoutTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testCheckingOutAccessoryRequiresCorrectPermission()
|
||||
{
|
||||
$this->actingAs(User::factory()->create())
|
||||
->post(route('accessories.checkout.store', Accessory::factory()->create()))
|
||||
->assertForbidden();
|
||||
}
|
||||
|
||||
public function testValidationWhenCheckingOutAccessory()
|
||||
{
|
||||
$this->actingAs(User::factory()->checkoutAccessories()->create())
|
||||
->post(route('accessories.checkout.store', Accessory::factory()->create()), [
|
||||
// missing assigned_to
|
||||
])
|
||||
->assertSessionHas('error');
|
||||
}
|
||||
|
||||
public function testAccessoryMustBeAvailableWhenCheckingOut()
|
||||
{
|
||||
$this->actingAs(User::factory()->checkoutAccessories()->create())
|
||||
->post(route('accessories.checkout.store', Accessory::factory()->withoutItemsRemaining()->create()), [
|
||||
'assigned_to' => User::factory()->create()->id,
|
||||
])
|
||||
->assertSessionHas('error');
|
||||
}
|
||||
|
||||
public function testAccessoryCanBeCheckedOut()
|
||||
{
|
||||
$accessory = Accessory::factory()->create();
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAs(User::factory()->checkoutAccessories()->create())
|
||||
->post(route('accessories.checkout.store', $accessory), [
|
||||
'assigned_to' => $user->id,
|
||||
]);
|
||||
|
||||
$this->assertTrue($accessory->users->contains($user));
|
||||
}
|
||||
|
||||
public function testUserSentNotificationUponCheckout()
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$accessory = Accessory::factory()->requiringAcceptance()->create();
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAs(User::factory()->checkoutAccessories()->create())
|
||||
->post(route('accessories.checkout.store', $accessory), [
|
||||
'assigned_to' => $user->id,
|
||||
]);
|
||||
|
||||
Notification::assertSentTo($user, CheckoutAccessoryNotification::class);
|
||||
}
|
||||
|
||||
public function testActionLogCreatedUponCheckout()
|
||||
{
|
||||
$accessory = Accessory::factory()->create();
|
||||
$actor = User::factory()->checkoutAccessories()->create();
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAs($actor)
|
||||
->post(route('accessories.checkout.store', $accessory), [
|
||||
'assigned_to' => $user->id,
|
||||
'note' => 'oh hi there',
|
||||
]);
|
||||
|
||||
$this->assertEquals(
|
||||
1,
|
||||
Actionlog::where([
|
||||
'action_type' => 'checkout',
|
||||
'target_id' => $user->id,
|
||||
'target_type' => User::class,
|
||||
'item_id' => $accessory->id,
|
||||
'item_type' => Accessory::class,
|
||||
'user_id' => $actor->id,
|
||||
'note' => 'oh hi there',
|
||||
])->count(),
|
||||
'Log entry either does not exist or there are more than expected'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Checkouts;
|
||||
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CheckoutConsumableNotification;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ConsumableCheckoutTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testCheckingOutConsumableRequiresCorrectPermission()
|
||||
{
|
||||
$this->actingAs(User::factory()->create())
|
||||
->post(route('consumables.checkout.store', Consumable::factory()->create()))
|
||||
->assertForbidden();
|
||||
}
|
||||
|
||||
public function testValidationWhenCheckingOutConsumable()
|
||||
{
|
||||
$this->actingAs(User::factory()->checkoutConsumables()->create())
|
||||
->post(route('consumables.checkout.store', Consumable::factory()->create()), [
|
||||
// missing assigned_to
|
||||
])
|
||||
->assertSessionHas('error');
|
||||
}
|
||||
|
||||
public function testConsumableMustBeAvailableWhenCheckingOut()
|
||||
{
|
||||
$this->actingAs(User::factory()->checkoutConsumables()->create())
|
||||
->post(route('consumables.checkout.store', Consumable::factory()->withoutItemsRemaining()->create()), [
|
||||
'assigned_to' => User::factory()->create()->id,
|
||||
])
|
||||
->assertSessionHas('error');
|
||||
}
|
||||
|
||||
public function testConsumableCanBeCheckedOut()
|
||||
{
|
||||
$consumable = Consumable::factory()->create();
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAs(User::factory()->checkoutConsumables()->create())
|
||||
->post(route('consumables.checkout.store', $consumable), [
|
||||
'assigned_to' => $user->id,
|
||||
]);
|
||||
|
||||
$this->assertTrue($user->consumables->contains($consumable));
|
||||
}
|
||||
|
||||
public function testUserSentNotificationUponCheckout()
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$consumable = Consumable::factory()->create();
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAs(User::factory()->checkoutConsumables()->create())
|
||||
->post(route('consumables.checkout.store', $consumable), [
|
||||
'assigned_to' => $user->id,
|
||||
]);
|
||||
|
||||
Notification::assertSentTo($user, CheckoutConsumableNotification::class);
|
||||
}
|
||||
|
||||
public function testActionLogCreatedUponCheckout()
|
||||
{
|
||||
$consumable = Consumable::factory()->create();
|
||||
$actor = User::factory()->checkoutConsumables()->create();
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAs($actor)
|
||||
->post(route('consumables.checkout.store', $consumable), [
|
||||
'assigned_to' => $user->id,
|
||||
'note' => 'oh hi there',
|
||||
]);
|
||||
|
||||
$this->assertEquals(
|
||||
1,
|
||||
Actionlog::where([
|
||||
'action_type' => 'checkout',
|
||||
'target_id' => $user->id,
|
||||
'target_type' => User::class,
|
||||
'item_id' => $consumable->id,
|
||||
'item_type' => Consumable::class,
|
||||
'user_id' => $actor->id,
|
||||
'note' => 'oh hi there',
|
||||
])->count(),
|
||||
'Log entry either does not exist or there are more than expected'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ class AccessoryWebhookTest extends TestCase
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$this->settings->enableWebhook();
|
||||
$this->settings->enableSlackWebhook();
|
||||
|
||||
event(new CheckoutableCheckedOut(
|
||||
Accessory::factory()->appleBtKeyboard()->create(),
|
||||
@@ -60,7 +60,7 @@ class AccessoryWebhookTest extends TestCase
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$this->settings->enableWebhook();
|
||||
$this->settings->enableSlackWebhook();
|
||||
|
||||
event(new CheckoutableCheckedIn(
|
||||
Accessory::factory()->appleBtKeyboard()->create(),
|
||||
|
||||
@@ -33,7 +33,7 @@ class AssetWebhookTest extends TestCase
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$this->settings->enableWebhook();
|
||||
$this->settings->enableSlackWebhook();
|
||||
|
||||
event(new CheckoutableCheckedOut(
|
||||
$this->createAsset(),
|
||||
@@ -73,7 +73,7 @@ class AssetWebhookTest extends TestCase
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$this->settings->enableWebhook();
|
||||
$this->settings->enableSlackWebhook();
|
||||
|
||||
event(new CheckoutableCheckedIn(
|
||||
$this->createAsset(),
|
||||
|
||||
@@ -20,7 +20,7 @@ class ComponentWebhookTest extends TestCase
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$this->settings->enableWebhook();
|
||||
$this->settings->enableSlackWebhook();
|
||||
|
||||
event(new CheckoutableCheckedOut(
|
||||
Component::factory()->ramCrucial8()->create(),
|
||||
@@ -36,7 +36,7 @@ class ComponentWebhookTest extends TestCase
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$this->settings->enableWebhook();
|
||||
$this->settings->enableSlackWebhook();
|
||||
|
||||
event(new CheckoutableCheckedIn(
|
||||
Component::factory()->ramCrucial8()->create(),
|
||||
|
||||
@@ -20,7 +20,7 @@ class ConsumableWebhookTest extends TestCase
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$this->settings->enableWebhook();
|
||||
$this->settings->enableSlackWebhook();
|
||||
|
||||
event(new CheckoutableCheckedOut(
|
||||
Consumable::factory()->cardstock()->create(),
|
||||
|
||||
@@ -32,7 +32,7 @@ class LicenseWebhookTest extends TestCase
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$this->settings->enableWebhook();
|
||||
$this->settings->enableSlackWebhook();
|
||||
|
||||
event(new CheckoutableCheckedOut(
|
||||
LicenseSeat::factory()->create(),
|
||||
@@ -72,7 +72,7 @@ class LicenseWebhookTest extends TestCase
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$this->settings->enableWebhook();
|
||||
$this->settings->enableSlackWebhook();
|
||||
|
||||
event(new CheckoutableCheckedIn(
|
||||
LicenseSeat::factory()->create(),
|
||||
|
||||
@@ -39,9 +39,10 @@ class Settings
|
||||
return $this->update(['full_multiple_companies_support' => 0]);
|
||||
}
|
||||
|
||||
public function enableWebhook(): Settings
|
||||
public function enableSlackWebhook(): Settings
|
||||
{
|
||||
return $this->update([
|
||||
'webhook_selected' => 'slack',
|
||||
'webhook_botname' => 'SnipeBot5000',
|
||||
'webhook_endpoint' => 'https://hooks.slack.com/services/NZ59/Q446/672N',
|
||||
'webhook_channel' => '#it',
|
||||
@@ -51,6 +52,7 @@ class Settings
|
||||
public function disableWebhook(): Settings
|
||||
{
|
||||
return $this->update([
|
||||
'webhook_selected' => '',
|
||||
'webhook_botname' => '',
|
||||
'webhook_endpoint' => '',
|
||||
'webhook_channel' => '',
|
||||
|
||||
@@ -7,6 +7,9 @@ use Exception;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* @group ldap
|
||||
*/
|
||||
class LdapTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user