mirror of
https://github.com/snipe/snipe-it.git
synced 2024-12-25 13:44:06 -08:00
Merge branch 'develop' into chore/sc-23725/livewire3
# Conflicts: # app/Livewire/LoginForm.php # package.json # resources/views/livewire/login-form.blade.php
This commit is contained in:
commit
1736bf5510
|
@ -17,6 +17,7 @@ use Illuminate\Contracts\Encryption\DecryptException;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Intervention\Image\ImageManagerStatic as Image;
|
use Intervention\Image\ImageManagerStatic as Image;
|
||||||
|
use Illuminate\Support\Facades\Session;
|
||||||
|
|
||||||
class Helper
|
class Helper
|
||||||
{
|
{
|
||||||
|
@ -1463,4 +1464,38 @@ class Helper
|
||||||
return $new_locale; // better that you have some weird locale that doesn't fit into our mappings anywhere than 'void'
|
return $new_locale; // better that you have some weird locale that doesn't fit into our mappings anywhere than 'void'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static public function getRedirectOption($request, $id, $table, $asset_id = null)
|
||||||
|
{
|
||||||
|
|
||||||
|
$redirect_option = Session::get('redirect_option');
|
||||||
|
$checkout_to_type = Session::get('checkout_to_type');
|
||||||
|
|
||||||
|
//return to index
|
||||||
|
if ($redirect_option == '0') {
|
||||||
|
switch ($table) {
|
||||||
|
case "Assets":
|
||||||
|
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.checkout.success'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//return to thing being assigned
|
||||||
|
if ($redirect_option == '1') {
|
||||||
|
switch ($table) {
|
||||||
|
case "Assets":
|
||||||
|
return redirect()->route('hardware.show', $id ? $id : $asset_id)->with('success', trans('admin/hardware/message.checkout.success'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//return to thing being assigned to
|
||||||
|
if ($redirect_option == '2') {
|
||||||
|
switch ($checkout_to_type) {
|
||||||
|
case 'user':
|
||||||
|
return redirect()->route('users.show', $request->assigned_user)->with('success', trans('admin/hardware/message.checkout.success'));
|
||||||
|
case 'location':
|
||||||
|
return redirect()->route('locations.show', $request->assigned_location)->with('success', trans('admin/hardware/message.checkout.success'));
|
||||||
|
case 'asset':
|
||||||
|
return redirect()->route('hardware.show', $request->assigned_asset)->with('success', trans('admin/hardware/message.checkout.success'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return redirect()->back()->with('error', trans('admin/hardware/message.checkout.error'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ use App\Models\LicenseSeat;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Redirect;
|
use Illuminate\Support\Facades\Redirect;
|
||||||
|
use Illuminate\Support\Facades\Session;
|
||||||
use Illuminate\Support\Facades\View;
|
use Illuminate\Support\Facades\View;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
@ -46,7 +47,7 @@ class AssetCheckinController extends Controller
|
||||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.already_checked_in'));
|
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.already_checked_in'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return view('hardware/checkin', compact('asset'))->with('statusLabel_list', Helper::statusLabelList())->with('backto', $backto);
|
return view('hardware/checkin', compact('asset'))->with('statusLabel_list', Helper::statusLabelList())->with('backto', $backto)->with('table_name', 'Assets');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -123,15 +124,12 @@ class AssetCheckinController extends Controller
|
||||||
$acceptance->delete();
|
$acceptance->delete();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Session::put('redirect_option', $request->get('redirect_option'));
|
||||||
// Was the asset updated?
|
// Was the asset updated?
|
||||||
if ($asset->save()) {
|
if ($asset->save()) {
|
||||||
|
|
||||||
event(new CheckoutableCheckedIn($asset, $target, Auth::user(), $request->input('note'), $checkin_at, $originalValues));
|
event(new CheckoutableCheckedIn($asset, $target, Auth::user(), $request->input('note'), $checkin_at, $originalValues));
|
||||||
|
return Helper::getRedirectOption($asset, $assetId, 'Assets');
|
||||||
if ((isset($user)) && ($backto == 'user')) {
|
|
||||||
return redirect()->route('users.show', $user->id)->with('success', trans('admin/hardware/message.checkin.success'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.checkin.success'));
|
|
||||||
}
|
}
|
||||||
// Redirect to the asset management page with error
|
// Redirect to the asset management page with error
|
||||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.error').$asset->getErrors());
|
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.error').$asset->getErrors());
|
||||||
|
|
|
@ -10,6 +10,7 @@ use App\Http\Requests\AssetCheckoutRequest;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Session;
|
||||||
|
|
||||||
class AssetCheckoutController extends Controller
|
class AssetCheckoutController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -35,7 +36,8 @@ class AssetCheckoutController extends Controller
|
||||||
|
|
||||||
if ($asset->availableForCheckout()) {
|
if ($asset->availableForCheckout()) {
|
||||||
return view('hardware/checkout', compact('asset'))
|
return view('hardware/checkout', compact('asset'))
|
||||||
->with('statusLabel_list', Helper::deployableStatusLabelList());
|
->with('statusLabel_list', Helper::deployableStatusLabelList())
|
||||||
|
->with('table_name', 'Assets');
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkout.not_available'));
|
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkout.not_available'));
|
||||||
|
@ -97,11 +99,12 @@ class AssetCheckoutController extends Controller
|
||||||
return redirect()->to("hardware/$assetId/checkout")->with('error', trans('general.error_user_company'));
|
return redirect()->to("hardware/$assetId/checkout")->with('error', trans('general.error_user_company'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($asset->checkOut($target, $admin, $checkout_at, $expected_checkin, $request->get('note'), $request->get('name'))) {
|
|
||||||
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.checkout.success'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Session::put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);
|
||||||
|
|
||||||
|
if ($asset->checkOut($target, $admin, $checkout_at, $expected_checkin, $request->get('note'), $request->get('name'))) {
|
||||||
|
return Helper::getRedirectOption($request, $assetId, 'Assets');
|
||||||
|
}
|
||||||
// Redirect to the asset management page with error
|
// Redirect to the asset management page with error
|
||||||
return redirect()->to("hardware/$assetId/checkout")->with('error', trans('admin/hardware/message.checkout.error').$asset->getErrors());
|
return redirect()->to("hardware/$assetId/checkout")->with('error', trans('admin/hardware/message.checkout.error').$asset->getErrors());
|
||||||
} catch (ModelNotFoundException $e) {
|
} catch (ModelNotFoundException $e) {
|
||||||
|
|
|
@ -71,8 +71,14 @@ class ConsumableCheckoutController extends Controller
|
||||||
|
|
||||||
$this->authorize('checkout', $consumable);
|
$this->authorize('checkout', $consumable);
|
||||||
|
|
||||||
|
// If the quantity is not present in the request or is not a positive integer, set it to 1
|
||||||
|
$quantity = $request->input('qty');
|
||||||
|
if (!isset($quantity) || !ctype_digit((string)$quantity) || $quantity <= 0) {
|
||||||
|
$quantity = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure there is at least one available to checkout
|
// Make sure there is at least one available to checkout
|
||||||
if ($consumable->numRemaining() <= 0) {
|
if ($consumable->numRemaining() <= 0 || $quantity > $consumable->numRemaining()) {
|
||||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.checkout.unavailable'));
|
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.checkout.unavailable'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,13 +94,14 @@ class ConsumableCheckoutController extends Controller
|
||||||
// Update the consumable data
|
// Update the consumable data
|
||||||
$consumable->assigned_to = e($request->input('assigned_to'));
|
$consumable->assigned_to = e($request->input('assigned_to'));
|
||||||
|
|
||||||
|
for($i = 0; $i < $quantity; $i++){
|
||||||
$consumable->users()->attach($consumable->id, [
|
$consumable->users()->attach($consumable->id, [
|
||||||
'consumable_id' => $consumable->id,
|
'consumable_id' => $consumable->id,
|
||||||
'user_id' => $admin_user->id,
|
'user_id' => $admin_user->id,
|
||||||
'assigned_to' => e($request->input('assigned_to')),
|
'assigned_to' => e($request->input('assigned_to')),
|
||||||
'note' => $request->input('note'),
|
'note' => $request->input('note'),
|
||||||
]);
|
]);
|
||||||
|
}
|
||||||
event(new CheckoutableCheckedOut($consumable, $user, Auth::user(), $request->input('note')));
|
event(new CheckoutableCheckedOut($consumable, $user, Auth::user(), $request->input('note')));
|
||||||
|
|
||||||
// Redirect to the new consumable page
|
// Redirect to the new consumable page
|
||||||
|
|
|
@ -563,6 +563,7 @@ class UsersController extends Controller
|
||||||
trans('general.accessories'),
|
trans('general.accessories'),
|
||||||
trans('general.consumables'),
|
trans('general.consumables'),
|
||||||
trans('general.groups'),
|
trans('general.groups'),
|
||||||
|
trans('general.permissions'),
|
||||||
trans('general.notes'),
|
trans('general.notes'),
|
||||||
trans('admin/users/table.activated'),
|
trans('admin/users/table.activated'),
|
||||||
trans('general.created_at'),
|
trans('general.created_at'),
|
||||||
|
@ -577,6 +578,19 @@ class UsersController extends Controller
|
||||||
$user_groups .= $user_group->name.', ';
|
$user_groups .= $user_group->name.', ';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$permissionstring = "";
|
||||||
|
|
||||||
|
if($user->isSuperUser()) {
|
||||||
|
$permissionstring = trans('general.superuser');
|
||||||
|
}
|
||||||
|
elseif($user->hasAccess('admin')) {
|
||||||
|
$permissionstring = trans('general.admin');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$permissionstring = trans('general.user');
|
||||||
|
}
|
||||||
|
|
||||||
// Add a new row with data
|
// Add a new row with data
|
||||||
$values = [
|
$values = [
|
||||||
$user->id,
|
$user->id,
|
||||||
|
@ -594,6 +608,7 @@ class UsersController extends Controller
|
||||||
$user->accessories->count(),
|
$user->accessories->count(),
|
||||||
$user->consumables->count(),
|
$user->consumables->count(),
|
||||||
$user_groups,
|
$user_groups,
|
||||||
|
$permissionstring,
|
||||||
$user->notes,
|
$user->notes,
|
||||||
($user->activated == '1') ? trans('general.yes') : trans('general.no'),
|
($user->activated == '1') ? trans('general.yes') : trans('general.no'),
|
||||||
$user->created_at,
|
$user->created_at,
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
<?php
|
|
||||||
namespace App\Livewire;
|
|
||||||
|
|
||||||
use Livewire\Component;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
|
|
||||||
class LoginForm extends Component
|
|
||||||
{
|
|
||||||
public $username = '';
|
|
||||||
public $password = '';
|
|
||||||
public $can_submit = false;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the validation rules for login
|
|
||||||
*
|
|
||||||
* @author A. Gianotto <snipe@snipe.net>
|
|
||||||
* @version v6.0
|
|
||||||
* @return Array
|
|
||||||
*/
|
|
||||||
public function rules()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'username' => 'required|string|max:255',
|
|
||||||
'password' => 'required',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform the validation
|
|
||||||
*
|
|
||||||
* @author A. Gianotto <snipe@snipe.net>
|
|
||||||
* @version v6.0
|
|
||||||
*/
|
|
||||||
public function updated($fields)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (is_null($fields) || empty($fields)) {
|
|
||||||
$this->can_submit = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$whatever = $this->validateOnly($fields);
|
|
||||||
|
|
||||||
$errors = $this->getErrorBag();
|
|
||||||
|
|
||||||
$this->can_submit = $this->username !== "" && $this->password !== "" && !$errors->has('username') && !$errors->has('password') ; // wait, what?
|
|
||||||
|
|
||||||
Log::info("Oy - can we submit yet?!".$this->can_submit);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Actually do the login thing
|
|
||||||
*
|
|
||||||
* @todo fix missing LDAP stuff maybe? Not sure if it
|
|
||||||
* makes sense to even do this via LiveWire, since
|
|
||||||
* our login system is pretty complicated.
|
|
||||||
*
|
|
||||||
* @author A. Gianotto <snipe@snipe.net>
|
|
||||||
* @version v6.0
|
|
||||||
*/
|
|
||||||
public function submitForm()
|
|
||||||
{
|
|
||||||
|
|
||||||
//$this->can_submit = true;
|
|
||||||
|
|
||||||
if (auth()->attempt($this->validate())) {
|
|
||||||
return redirect()->intended('/');
|
|
||||||
} else {
|
|
||||||
return session()->flash('error', trans('auth/message.account_not_found'));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
25
package-lock.json
generated
25
package-lock.json
generated
|
@ -30,7 +30,7 @@
|
||||||
"less-loader": "^6.0",
|
"less-loader": "^6.0",
|
||||||
"list.js": "^1.5.0",
|
"list.js": "^1.5.0",
|
||||||
"morris.js": "github:morrisjs/morris.js",
|
"morris.js": "github:morrisjs/morris.js",
|
||||||
"papaparse": "^4.3.3",
|
"papaparse": "5.2.0",
|
||||||
"select2": "4.0.13",
|
"select2": "4.0.13",
|
||||||
"sheetjs": "^2.0.0",
|
"sheetjs": "^2.0.0",
|
||||||
"signature_pad": "^4.2.0",
|
"signature_pad": "^4.2.0",
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"all-contributors-cli": "^6.26.1",
|
"all-contributors-cli": "^6.26.1",
|
||||||
"axios": "^0.27.2",
|
"axios": "^1.7.2",
|
||||||
"babel-preset-latest": "^6.24.1",
|
"babel-preset-latest": "^6.24.1",
|
||||||
"jquery": "<3.6.0",
|
"jquery": "<3.6.0",
|
||||||
"laravel-mix": "^6.0.49",
|
"laravel-mix": "^6.0.49",
|
||||||
|
@ -2840,12 +2840,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "0.27.2",
|
"version": "1.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz",
|
||||||
|
"integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.14.9",
|
"follow-redirects": "^1.15.6",
|
||||||
"form-data": "^4.0.0"
|
"form-data": "^4.0.0",
|
||||||
|
"proxy-from-env": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/babel-code-frame": {
|
"node_modules/babel-code-frame": {
|
||||||
|
@ -8325,8 +8327,9 @@
|
||||||
"license": "(MIT AND Zlib)"
|
"license": "(MIT AND Zlib)"
|
||||||
},
|
},
|
||||||
"node_modules/papaparse": {
|
"node_modules/papaparse": {
|
||||||
"version": "4.6.3",
|
"version": "5.2.0",
|
||||||
"license": "MIT"
|
"resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-ylq1wgUSnagU+MKQtNeVqrPhZuMYBvOSL00DHycFTCxownF95gpLAk1HiHdUW77N8yxRq1qHXLdlIPyBSG9NSA=="
|
||||||
},
|
},
|
||||||
"node_modules/param-case": {
|
"node_modules/param-case": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
|
@ -9164,6 +9167,12 @@
|
||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/proxy-from-env": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/prr": {
|
"node_modules/prr": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"all-contributors-cli": "^6.26.1",
|
"all-contributors-cli": "^6.26.1",
|
||||||
"axios": "^0.27.2",
|
"axios": "^1.7.2",
|
||||||
"babel-preset-latest": "^6.24.1",
|
"babel-preset-latest": "^6.24.1",
|
||||||
"jquery": "<3.6.0",
|
"jquery": "<3.6.0",
|
||||||
"laravel-mix": "^6.0.49",
|
"laravel-mix": "^6.0.49",
|
||||||
|
@ -30,6 +30,7 @@
|
||||||
"acorn-import-assertions": "^1.9.0",
|
"acorn-import-assertions": "^1.9.0",
|
||||||
"admin-lte": "^2.4.18",
|
"admin-lte": "^2.4.18",
|
||||||
"ajv": "^6.12.6",
|
"ajv": "^6.12.6",
|
||||||
|
"alpinejs": "^3.13.10",
|
||||||
"blueimp-file-upload": "^9.34.0",
|
"blueimp-file-upload": "^9.34.0",
|
||||||
"bootstrap": "^3.4.1",
|
"bootstrap": "^3.4.1",
|
||||||
"bootstrap-colorpicker": "^2.5.3",
|
"bootstrap-colorpicker": "^2.5.3",
|
||||||
|
@ -50,7 +51,7 @@
|
||||||
"less-loader": "^6.0",
|
"less-loader": "^6.0",
|
||||||
"list.js": "^1.5.0",
|
"list.js": "^1.5.0",
|
||||||
"morris.js": "github:morrisjs/morris.js",
|
"morris.js": "github:morrisjs/morris.js",
|
||||||
"papaparse": "^4.3.3",
|
"papaparse": "5.2.0",
|
||||||
"select2": "4.0.13",
|
"select2": "4.0.13",
|
||||||
"sheetjs": "^2.0.0",
|
"sheetjs": "^2.0.0",
|
||||||
"signature_pad": "^4.2.0",
|
"signature_pad": "^4.2.0",
|
||||||
|
|
Binary file not shown.
Binary file not shown.
BIN
public/js/dist/all.js
vendored
BIN
public/js/dist/all.js
vendored
Binary file not shown.
|
@ -1,10 +1,9 @@
|
||||||
{
|
{
|
||||||
"/js/build/app.js": "/js/build/app.js?id=337bd2424ba19bb3c8f200e266caa513",
|
"/js/build/app.js": "/js/build/app.js?id=bcf31142100dae10c9e075884f901d56",
|
||||||
"/css/dist/skins/skin-red.css": "/css/dist/skins/skin-red.css?id=44bf834f2110504a793dadec132a5898",
|
"/css/dist/skins/skin-red.css": "/css/dist/skins/skin-red.css?id=44bf834f2110504a793dadec132a5898",
|
||||||
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=f677207c6cf9678eb539abecb408c374",
|
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=f677207c6cf9678eb539abecb408c374",
|
||||||
"/css/build/overrides.css": "/css/build/overrides.css?id=004835e70ed3ae2e2340162b7a37c752",
|
"/css/build/overrides.css": "/css/build/overrides.css?id=004835e70ed3ae2e2340162b7a37c752",
|
||||||
"/css/build/app.css": "/css/build/app.css?id=7ecac57fc8cf6fdbe447c18d5f2ae7bc",
|
"/css/build/app.css": "/css/build/app.css?id=7ecac57fc8cf6fdbe447c18d5f2ae7bc",
|
||||||
"/css/build/AdminLTE.css": "/css/build/AdminLTE.css?id=4ea0068716c1bb2434d87a16d51b98c9",
|
|
||||||
"/css/dist/skins/skin-orange.css": "/css/dist/skins/skin-orange.css?id=6f0563e726c2fe4fab4026daaa5bfdf2",
|
"/css/dist/skins/skin-orange.css": "/css/dist/skins/skin-orange.css?id=6f0563e726c2fe4fab4026daaa5bfdf2",
|
||||||
"/css/dist/skins/skin-orange-dark.css": "/css/dist/skins/skin-orange-dark.css?id=620b684d9dd9d3bb5fdda00a3a2467c3",
|
"/css/dist/skins/skin-orange-dark.css": "/css/dist/skins/skin-orange-dark.css?id=620b684d9dd9d3bb5fdda00a3a2467c3",
|
||||||
"/css/dist/skins/skin-blue-dark.css": "/css/dist/skins/skin-blue-dark.css?id=23f2e8df6b60e8d9816e645cc5000874",
|
"/css/dist/skins/skin-blue-dark.css": "/css/dist/skins/skin-blue-dark.css?id=23f2e8df6b60e8d9816e645cc5000874",
|
||||||
|
@ -30,9 +29,9 @@
|
||||||
"/css/webfonts/fa-v4compatibility.ttf": "/css/webfonts/fa-v4compatibility.ttf?id=8994b282f9f3b7a00380bb1e2731a4bf",
|
"/css/webfonts/fa-v4compatibility.ttf": "/css/webfonts/fa-v4compatibility.ttf?id=8994b282f9f3b7a00380bb1e2731a4bf",
|
||||||
"/css/webfonts/fa-v4compatibility.woff2": "/css/webfonts/fa-v4compatibility.woff2?id=111e341dba724e1df946e8d1f406a7bd",
|
"/css/webfonts/fa-v4compatibility.woff2": "/css/webfonts/fa-v4compatibility.woff2?id=111e341dba724e1df946e8d1f406a7bd",
|
||||||
"/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=5f79123a6750afd34dbf565faec3dda3",
|
"/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=5f79123a6750afd34dbf565faec3dda3",
|
||||||
"/js/build/vendor.js": "/js/build/vendor.js?id=179bfe20e8767f7df32658c6b5a10ca3",
|
"/js/build/vendor.js": "/js/build/vendor.js?id=2f71c05daf36d9ec4852d1a8c87bc74c",
|
||||||
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=e5918703a22f8992c4c98f1dbbecb8f7",
|
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=e5918703a22f8992c4c98f1dbbecb8f7",
|
||||||
"/js/dist/all.js": "/js/dist/all.js?id=e37ce44903f83119fe3d52717200022e",
|
"/js/dist/all.js": "/js/dist/all.js?id=aa7cb7c65a042b69e46aeaa93a7d50ec",
|
||||||
"/js/dist/all-defer.js": "/js/dist/all-defer.js?id=75d841799f917cbcacf6b87698379726",
|
"/js/dist/all-defer.js": "/js/dist/all-defer.js?id=75d841799f917cbcacf6b87698379726",
|
||||||
"/css/dist/skins/skin-green.min.css": "/css/dist/skins/skin-green.min.css?id=0a82a6ae6bb4e58fe62d162c4fb50397",
|
"/css/dist/skins/skin-green.min.css": "/css/dist/skins/skin-green.min.css?id=0a82a6ae6bb4e58fe62d162c4fb50397",
|
||||||
"/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=ec0a01609bec55e90f0692d86cb81625",
|
"/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=ec0a01609bec55e90f0692d86cb81625",
|
||||||
|
|
|
@ -143,6 +143,7 @@ return [
|
||||||
'generate_labels' => 'Generate Labels',
|
'generate_labels' => 'Generate Labels',
|
||||||
'github_markdown' => 'This field accepts <a href="https://help.github.com/articles/github-flavored-markdown/">Github flavored markdown</a>.',
|
'github_markdown' => 'This field accepts <a href="https://help.github.com/articles/github-flavored-markdown/">Github flavored markdown</a>.',
|
||||||
'groups' => 'Groups',
|
'groups' => 'Groups',
|
||||||
|
'permission_level' => 'Permission Level',
|
||||||
'gravatar_email' => 'Gravatar Email Address',
|
'gravatar_email' => 'Gravatar Email Address',
|
||||||
'gravatar_url' => '<a href="http://gravatar.com"><small>Change your avatar at Gravatar.com</small></a>.',
|
'gravatar_url' => '<a href="http://gravatar.com"><small>Change your avatar at Gravatar.com</small></a>.',
|
||||||
'history' => 'History',
|
'history' => 'History',
|
||||||
|
@ -274,6 +275,7 @@ return [
|
||||||
'status_labels' => 'Status Labels',
|
'status_labels' => 'Status Labels',
|
||||||
'status' => 'Status',
|
'status' => 'Status',
|
||||||
'accept_eula' => 'Acceptance Agreement',
|
'accept_eula' => 'Acceptance Agreement',
|
||||||
|
'superuser' => 'Superuser',
|
||||||
'supplier' => 'Supplier',
|
'supplier' => 'Supplier',
|
||||||
'suppliers' => 'Suppliers',
|
'suppliers' => 'Suppliers',
|
||||||
'sure_to_delete' => 'Are you sure you wish to delete',
|
'sure_to_delete' => 'Are you sure you wish to delete',
|
||||||
|
|
|
@ -39,6 +39,9 @@ return [
|
||||||
'order' => 'Order Number',
|
'order' => 'Order Number',
|
||||||
'qr' => 'QR Code',
|
'qr' => 'QR Code',
|
||||||
'requestable' => 'Users may request this asset',
|
'requestable' => 'Users may request this asset',
|
||||||
|
'redirect_to_all' => 'Return to all :type',
|
||||||
|
'redirect_to_type' => 'Go to :type',
|
||||||
|
'redirect_to_checked_out_to' => 'Go to Checked Out to',
|
||||||
'select_statustype' => 'Select Status Type',
|
'select_statustype' => 'Select Status Type',
|
||||||
'serial' => 'Serial',
|
'serial' => 'Serial',
|
||||||
'status' => 'Status',
|
'status' => 'Status',
|
||||||
|
|
|
@ -11,6 +11,9 @@ return [
|
||||||
'activity_report' => 'Activity Report',
|
'activity_report' => 'Activity Report',
|
||||||
'address' => 'Address',
|
'address' => 'Address',
|
||||||
'admin' => 'Admin',
|
'admin' => 'Admin',
|
||||||
|
'admin_tooltip' => 'This user has admin privileges',
|
||||||
|
'superuser' => 'Superuser',
|
||||||
|
'superuser_tooltip' => 'This user has superuser privileges',
|
||||||
'administrator' => 'Administrator',
|
'administrator' => 'Administrator',
|
||||||
'add_seats' => 'Added seats',
|
'add_seats' => 'Added seats',
|
||||||
'age' => "Age",
|
'age' => "Age",
|
||||||
|
|
|
@ -66,6 +66,18 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
<!-- Checkout QTY -->
|
||||||
|
<div class="form-group {{ $errors->has('qty') ? 'error' : '' }} ">
|
||||||
|
<label for="qty" class="col-md-3 control-label">{{ trans('general.qty') }}</label>
|
||||||
|
<div class="col-md-7 col-sm-12 required">
|
||||||
|
<div class="col-md-2" style="padding-left:0px">
|
||||||
|
<input class="form-control" type="number" name="qty" id="qty" value="1" min="1" max="{{$consumable->numRemaining()}}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{!! $errors->first('qty', '<div class="col-md-8 col-md-offset-3"><span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span></div>') !!}
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Note -->
|
<!-- Note -->
|
||||||
<div class="form-group {{ $errors->has('note') ? 'error' : '' }}">
|
<div class="form-group {{ $errors->has('note') ? 'error' : '' }}">
|
||||||
<label for="note" class="col-md-3 control-label">{{ trans('admin/hardware/form.notes') }}</label>
|
<label for="note" class="col-md-3 control-label">{{ trans('admin/hardware/form.notes') }}</label>
|
||||||
|
|
|
@ -101,10 +101,7 @@
|
||||||
{!! $errors->first('note', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
{!! $errors->first('note', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-footer">
|
@include ('partials.forms.redirect_submit_options', ['route' => 'hardware.index', 'table_name' => $table_name, 'type'=> $asset->model->name, 'checkin' => true])
|
||||||
<a class="btn btn-link" href="{{ URL::previous() }}"> {{ trans('button.cancel') }}</a>
|
|
||||||
<button type="submit" class="btn btn-primary pull-right"><i class="fas fa-check icon-white" aria-hidden="true"></i> {{ trans('general.checkin') }}</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
</div> <!--/.col-md-12-->
|
</div> <!--/.col-md-12-->
|
||||||
</div> <!--/.box-body-->
|
</div> <!--/.box-body-->
|
||||||
|
|
|
@ -141,10 +141,7 @@
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
</div> <!--/.box-body-->
|
</div> <!--/.box-body-->
|
||||||
<div class="box-footer">
|
@include ('partials.forms.redirect_submit_options', ['route' => 'hardware.index', 'table_name' => $table_name, 'type'=> $asset->model->name, 'checkin' => false])
|
||||||
<a class="btn btn-link" href="{{ URL::previous() }}"> {{ trans('button.cancel') }}</a>
|
|
||||||
<button type="submit" class="btn btn-primary pull-right"><i class="fas fa-check icon-white" aria-hidden="true"></i> {{ trans('general.checkout') }}</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div> <!--/.col-md-7-->
|
</div> <!--/.col-md-7-->
|
||||||
|
|
|
@ -1,106 +0,0 @@
|
||||||
<div>
|
|
||||||
<form role="form" method="POST" action="{{ route('login') }}" autocomplete="false" wire:submit="submitForm">
|
|
||||||
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
|
|
||||||
|
|
||||||
<!-- this is a hack to prevent Chrome from trying to autocomplete fields -->
|
|
||||||
<input type="text" name="prevent_autofill" id="prevent_autofill" value="" style="display:none;" aria-hidden="true">
|
|
||||||
<input type="password" name="password_fake" id="password_fake" value="" style="display:none;" aria-hidden="true">
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
|
||||||
|
|
||||||
<div class="col-md-4 col-md-offset-4">
|
|
||||||
|
|
||||||
<div class="box login-box">
|
|
||||||
<div class="box-header with-border">
|
|
||||||
<h1 class="box-title"> {{ trans('auth/general.login_prompt') }}</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="login-box-body">
|
|
||||||
<div class="row">
|
|
||||||
|
|
||||||
@if ($snipeSettings->login_note)
|
|
||||||
<div class="col-md-12">
|
|
||||||
<div class="alert alert-info">
|
|
||||||
{!! Parsedown::instance()->text(e($snipeSettings->login_note)) !!}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<!-- Notifications -->
|
|
||||||
@include('notifications')
|
|
||||||
|
|
||||||
<div class="col-md-12">
|
|
||||||
<!-- CSRF Token -->
|
|
||||||
|
|
||||||
<fieldset>
|
|
||||||
|
|
||||||
<div class="form-group{{ $errors->has('username') ? ' has-error' : '' }}">
|
|
||||||
<label for="username">
|
|
||||||
<i class="fas fa-user" aria-hidden="true"></i>
|
|
||||||
{{ trans('admin/users/table.username') }}
|
|
||||||
</label>
|
|
||||||
<input class="form-control" placeholder="{{ trans('admin/users/table.username') }}" name="username" type="text" autocomplete="off" wire:model.live="username">
|
|
||||||
@error('username')
|
|
||||||
<span class="alert-msg">
|
|
||||||
{{ $message }}
|
|
||||||
</span>
|
|
||||||
@enderror
|
|
||||||
</div>
|
|
||||||
<div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
|
|
||||||
<label for="password">
|
|
||||||
<i class="fas fa-key" aria-hidden="true"></i>
|
|
||||||
{{ trans('admin/users/table.password') }}
|
|
||||||
</label>
|
|
||||||
<input class="form-control" placeholder="{{ trans('admin/users/table.password') }}" name="password" type="password" wire:model.live="password" autocomplete="off">
|
|
||||||
@error('password')
|
|
||||||
<span class="alert-msg">
|
|
||||||
{{ $message }}
|
|
||||||
</span>
|
|
||||||
@enderror
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="checkbox">
|
|
||||||
<label class="form-control">
|
|
||||||
<input name="remember" type="checkbox" value="1">
|
|
||||||
{{ trans('auth/general.remember_me') }}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
</div> <!-- end col-md-12 -->
|
|
||||||
|
|
||||||
</div> <!-- end row -->
|
|
||||||
|
|
||||||
@if ($snipeSettings->saml_enabled)
|
|
||||||
<div class="row">
|
|
||||||
<div class="text-right col-md-12">
|
|
||||||
<a href="{{ route('saml.login') }}">{{ trans('auth/general.saml_login') }}</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="box-footer">
|
|
||||||
<button class="btn btn-lg btn-primary btn-block" type="submit"{{ $can_submit ? '' : ' disabled' }}>
|
|
||||||
<i wire:loading wire:target='submitForm' class="fas fa-spin fa-spinner"></i> {{ trans('auth/general.login') }}</button>
|
|
||||||
</div>
|
|
||||||
<div class="text-right col-md-12 col-sm-12 col-xs-12" style="padding-top: 10px;">
|
|
||||||
@if ($snipeSettings->custom_forgot_pass_url)
|
|
||||||
<a href="{{ $snipeSettings->custom_forgot_pass_url }}" rel="noopener">{{ trans('auth/general.forgot_password') }}</a>
|
|
||||||
@else
|
|
||||||
<a href="{{ route('password.request') }}">{{ trans('auth/general.forgot_password') }}</a>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div> <!-- end login box -->
|
|
||||||
|
|
||||||
</div> <!-- col-md-4 -->
|
|
||||||
|
|
||||||
</div> <!-- end row -->
|
|
||||||
</div> <!-- end container -->
|
|
||||||
</form>
|
|
||||||
|
|
||||||
</div>
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
<div class="box-footer">
|
||||||
|
<a class="btn btn-link" href="{{ route($route) }}">{{ trans('button.cancel') }}</a>
|
||||||
|
<button type="submit" class="btn btn-primary pull-right"><i class="fas fa-check icon-white" aria-hidden="true"></i> {{$checkin ? trans('general.checkin') : trans('general.checkout') }}</button>
|
||||||
|
<div class="btn-group pull-right" style="margin-right:5px;">
|
||||||
|
<select class="redirect-options form-control" name="redirect_option">
|
||||||
|
<option {{(Session::get('redirect_option')=="0" || (Session::get('redirect_option')=="2" && $checkin)) ? 'selected' : ''}} value="0">{{trans('admin/hardware/form.redirect_to_all', ['type' => $table_name])}}</option>
|
||||||
|
<option {{Session::get('redirect_option')=="1" ? 'selected' : ''}} value="1">{{trans('admin/hardware/form.redirect_to_type', ['type' => $type])}}</option>
|
||||||
|
<option {{Session::get('redirect_option')=="2" && !$checkin ? 'selected' : ''}}{{$checkin ? 'disabled hidden' : ''}} value="2" >{{trans('admin/hardware/form.redirect_to_checked_out_to')}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div> <!-- /.box-->
|
|
@ -167,7 +167,7 @@
|
||||||
|
|
||||||
@if (($user->isSuperUser()) || ($user->hasAccess('admin')))
|
@if (($user->isSuperUser()) || ($user->hasAccess('admin')))
|
||||||
<i class="fas fa-crown fa-2x{{ ($user->isSuperUser()) ? ' text-danger' : ' text-orange'}}"></i>
|
<i class="fas fa-crown fa-2x{{ ($user->isSuperUser()) ? ' text-danger' : ' text-orange'}}"></i>
|
||||||
<div class="{{ ($user->isSuperUser()) ? 'text-danger' : ' text-orange'}}" style="font-weight: bold">{{ ($user->isSuperUser()) ? 'superadmin' : 'admin'}}</div>
|
<div class="{{ ($user->isSuperUser()) ? 'text-danger' : ' text-orange'}}" style="font-weight: bold">{{ ($user->isSuperUser()) ? strtolower(trans('general.superuser')) : strtolower(trans('general.admin')) }}</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -309,9 +309,9 @@
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
|
|
||||||
@if ($user->isSuperUser())
|
@if ($user->isSuperUser())
|
||||||
<label class="label label-danger"><i class="fas fa-crown" title="superuser"></i></label>
|
<label class="label label-danger" data-tooltip="true" title="{{ trans('general.superuser_tooltip') }}"><i class="fas fa-crown" title="{{ trans('general.superuser') }}"></i></label>
|
||||||
@elseif ($user->hasAccess('admin'))
|
@elseif ($user->hasAccess('admin'))
|
||||||
<label class="label label-warning"><i class="fas fa-crown" title="admin"></i></label>
|
<label class="label label-warning" data-tooltip="true" title="{{ trans('general.admin_tooltip') }}"><i class="fas fa-crown" title="{{ trans('general.admin') }}"></i></label>
|
||||||
@endif
|
@endif
|
||||||
{{ $user->username }}
|
{{ $user->username }}
|
||||||
|
|
||||||
|
|
|
@ -51,14 +51,13 @@ class AssetCheckinTest extends TestCase
|
||||||
|
|
||||||
$this->actingAs(User::factory()->checkinAssets()->create())
|
$this->actingAs(User::factory()->checkinAssets()->create())
|
||||||
->post(
|
->post(
|
||||||
route('hardware.checkin.store', ['assetId' => $asset->id, 'backto' => 'user']),
|
route('hardware.checkin.store', ['assetId' => $asset->id]),
|
||||||
[
|
[
|
||||||
'name' => 'Changed Name',
|
'name' => 'Changed Name',
|
||||||
'status_id' => $status->id,
|
'status_id' => $status->id,
|
||||||
'location_id' => $location->id,
|
'location_id' => $location->id,
|
||||||
],
|
],
|
||||||
)
|
);
|
||||||
->assertRedirect(route('users.show', $user));
|
|
||||||
|
|
||||||
$this->assertNull($asset->refresh()->assignedTo);
|
$this->assertNull($asset->refresh()->assignedTo);
|
||||||
$this->assertNull($asset->expected_checkin);
|
$this->assertNull($asset->expected_checkin);
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
namespace Tests\Unit\Helpers;
|
namespace Tests\Unit\Helpers;
|
||||||
|
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Support\Facades\Redirect;
|
||||||
|
use Illuminate\Support\Facades\Session;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class HelperTest extends TestCase
|
class HelperTest extends TestCase
|
||||||
|
@ -25,4 +28,60 @@ class HelperTest extends TestCase
|
||||||
$this->settings->set(['digit_separator' => '1.234,56']);
|
$this->settings->set(['digit_separator' => '1.234,56']);
|
||||||
$this->assertSame(12.34, Helper::ParseCurrency('12,34'));
|
$this->assertSame(12.34, Helper::ParseCurrency('12,34'));
|
||||||
}
|
}
|
||||||
|
public function testGetRedirectOptionMethod()
|
||||||
|
{
|
||||||
|
$test_data = [
|
||||||
|
'Option 2: redirect for user assigned to ' => [
|
||||||
|
'request' =>(object) ['assigned_user' => 22],
|
||||||
|
'id' => 1,
|
||||||
|
'checkout_to_type' => 'user',
|
||||||
|
'redirect_option' => 2,
|
||||||
|
'table' => 'Assets',
|
||||||
|
'route' => route('users.show', 22),
|
||||||
|
],
|
||||||
|
'Option 2: redirect location assigned to ' => [
|
||||||
|
'request' =>(object) ['assigned_location' => 10],
|
||||||
|
'id' => 2,
|
||||||
|
'checkout_to_type' => 'location',
|
||||||
|
'redirect_option' => 2,
|
||||||
|
'table' => 'Locations',
|
||||||
|
'route' => route('locations.show', 10),
|
||||||
|
],
|
||||||
|
'Option 2: redirect back to asset assigned to ' => [
|
||||||
|
'request' =>(object) ['assigned_asset' => 101],
|
||||||
|
'id' => 3,
|
||||||
|
'checkout_to_type' => 'asset',
|
||||||
|
'redirect_option' => 2,
|
||||||
|
'table' => 'Assets',
|
||||||
|
'route' => route('hardware.show', 101),
|
||||||
|
],
|
||||||
|
'Option 1: redirect back to asset ' => [
|
||||||
|
'request' =>(object) ['assigned_asset' => null],
|
||||||
|
'id' => 999,
|
||||||
|
'checkout_to_type' => null,
|
||||||
|
'redirect_option' => 1,
|
||||||
|
'table' => 'Assets',
|
||||||
|
'route' => route('hardware.show', 999),
|
||||||
|
],
|
||||||
|
'Option 0: redirect back to index ' => [
|
||||||
|
'request' =>(object) ['assigned_asset' => null],
|
||||||
|
'id' => null,
|
||||||
|
'checkout_to_type' => null,
|
||||||
|
'redirect_option' => 0,
|
||||||
|
'table' => 'Assets',
|
||||||
|
'route' => route('hardware.index'),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($test_data as $scenario => $data ) {
|
||||||
|
|
||||||
|
Session::put('redirect_option', $data['redirect_option']);
|
||||||
|
Session::put('checkout_to_type', $data['checkout_to_type']);
|
||||||
|
|
||||||
|
$redirect = Helper::getRedirectOption($data['request'],$data['id'], $data['table']);
|
||||||
|
|
||||||
|
$this->assertInstanceOf(RedirectResponse::class, $redirect);
|
||||||
|
$this->assertEquals($data['route'], $redirect->getTargetUrl(), $scenario.'failed.');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue