Merge branch 'develop' into feature/improve-checkout-asset-mail-wording

This commit is contained in:
Marcus Moore 2025-04-02 12:01:53 -07:00
commit af88ce5801
No known key found for this signature in database
130 changed files with 3765 additions and 2392 deletions

View file

@ -3307,6 +3307,15 @@
"contributions": [
"code"
]
},
{
"login": "ntaylor-86",
"name": "Nathan Taylor",
"avatar_url": "https://avatars.githubusercontent.com/u/28693782?v=4",
"profile": "https://github.com/ntaylor-86",
"contributions": [
"code"
]
}
]
}

View file

@ -35,6 +35,7 @@ DB_USERNAME=snipeit
DB_PASSWORD=changeme1234
DB_PREFIX=null
DB_DUMP_PATH='/usr/bin'
DB_DUMP_SKIP_SSL=true
DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_unicode_ci

View file

@ -35,6 +35,7 @@ DB_PASSWORD=changeme1234
MYSQL_ROOT_PASSWORD=changeme1234
DB_PREFIX=null
DB_DUMP_PATH='/usr/bin'
DB_DUMP_SKIP_SSL=true
DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_unicode_ci

View file

@ -30,6 +30,7 @@ DB_USERNAME=null
DB_PASSWORD=null
DB_PREFIX=null
DB_DUMP_PATH='/usr/bin'
DB_DUMP_SKIP_SSL=false
DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_unicode_ci
DB_SANITIZE_BY_DEFAULT=false

View file

@ -54,6 +54,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
| [<img src="https://avatars.githubusercontent.com/u/64061710?v=4" width="110px;"/><br /><sub>U-H-T</sub>](https://github.com/U-H-T)<br />[💻](https://github.com/snipe/snipe-it/commits?author=U-H-T "Code") | [<img src="https://avatars.githubusercontent.com/u/5395363?v=4" width="110px;"/><br /><sub>Matt Tyree</sub>](https://github.com/Tyree)<br />[📖](https://github.com/snipe/snipe-it/commits?author=Tyree "Documentation") | [<img src="https://avatars.githubusercontent.com/u/292081?v=4" width="110px;"/><br /><sub>Florent Bervas</sub>](http://spoontux.net)<br />[💻](https://github.com/snipe/snipe-it/commits?author=FlorentDotMe "Code") | [<img src="https://avatars.githubusercontent.com/u/4498077?v=4" width="110px;"/><br /><sub>Daniel Albertsen</sub>](https://ditscheri.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dbakan "Code") | [<img src="https://avatars.githubusercontent.com/u/100710244?v=4" width="110px;"/><br /><sub>r-xyz</sub>](https://github.com/r-xyz)<br />[💻](https://github.com/snipe/snipe-it/commits?author=r-xyz "Code") | [<img src="https://avatars.githubusercontent.com/u/47491036?v=4" width="110px;"/><br /><sub>Steven Mainor</sub>](https://github.com/DrekiDegga)<br />[💻](https://github.com/snipe/snipe-it/commits?author=DrekiDegga "Code") | [<img src="https://avatars.githubusercontent.com/u/65785975?v=4" width="110px;"/><br /><sub>arne-kroeger</sub>](https://github.com/arne-kroeger)<br />[💻](https://github.com/snipe/snipe-it/commits?author=arne-kroeger "Code") |
| [<img src="https://avatars.githubusercontent.com/u/167117705?v=4" width="110px;"/><br /><sub>Glukose1</sub>](https://github.com/Glukose1)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Glukose1 "Code") | [<img src="https://avatars.githubusercontent.com/u/1197791?v=4" width="110px;"/><br /><sub>Scarzy</sub>](https://github.com/Scarzy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Scarzy "Code") | [<img src="https://avatars.githubusercontent.com/u/37372069?v=4" width="110px;"/><br /><sub>setpill</sub>](https://github.com/setpill)<br />[💻](https://github.com/snipe/snipe-it/commits?author=setpill "Code") | [<img src="https://avatars.githubusercontent.com/u/3755203?v=4" width="110px;"/><br /><sub>swift2512</sub>](https://github.com/swift2512)<br />[🐛](https://github.com/snipe/snipe-it/issues?q=author%3Aswift2512 "Bug reports") | [<img src="https://avatars.githubusercontent.com/u/6136439?v=4" width="110px;"/><br /><sub>Darren Rainey</sub>](https://darrenraineys.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=DarrenRainey "Code") | [<img src="https://avatars.githubusercontent.com/u/133033121?v=4" width="110px;"/><br /><sub>maciej-poleszczyk</sub>](https://github.com/maciej-poleszczyk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=maciej-poleszczyk "Code") | [<img src="https://avatars.githubusercontent.com/u/143394709?v=4" width="110px;"/><br /><sub>Sebastian Groß</sub>](https://github.com/sgross-emlix)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sgross-emlix "Code") |
| [<img src="https://avatars.githubusercontent.com/u/41107778?v=4" width="110px;"/><br /><sub>Anouar Touati</sub>](https://github.com/AnouarTouati)<br />[💻](https://github.com/snipe/snipe-it/commits?author=AnouarTouati "Code") | [<img src="https://avatars.githubusercontent.com/u/25596663?v=4" width="110px;"/><br /><sub>aHVzY2g</sub>](https://github.com/aHVzY2g)<br />[💻](https://github.com/snipe/snipe-it/commits?author=aHVzY2g "Code") | [<img src="https://avatars.githubusercontent.com/u/13408130?v=4" width="110px;"/><br /><sub>林博仁 Buo-ren Lin</sub>](https://brlin.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=brlin-tw "Code") | [<img src="https://avatars.githubusercontent.com/u/18550946?v=4" width="110px;"/><br /><sub>Adugna Gizaw</sub>](https://orbalia.pythonanywhere.com/)<br />[🌍](#translation-addex12 "Translation") | [<img src="https://avatars.githubusercontent.com/u/760989?v=4" width="110px;"/><br /><sub>Jesse Ostrander</sub>](https://github.com/jostrander)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jostrander "Code") | [<img src="https://avatars.githubusercontent.com/u/31522486?v=4" width="110px;"/><br /><sub>James M</sub>](https://github.com/azmcnutt)<br />[💻](https://github.com/snipe/snipe-it/commits?author=azmcnutt "Code") | [<img src="https://avatars.githubusercontent.com/u/5183146?v=4" width="110px;"/><br /><sub>Fiala06</sub>](https://github.com/Fiala06)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Fiala06 "Code") |
| [<img src="https://avatars.githubusercontent.com/u/28693782?v=4" width="110px;"/><br /><sub>Nathan Taylor</sub>](https://github.com/ntaylor-86)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ntaylor-86 "Code") |
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!

View file

@ -0,0 +1,48 @@
<?php
namespace App\Actions\CheckoutRequests;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\Company;
use App\Models\Setting;
use App\Models\User;
use App\Notifications\RequestAssetCancelation;
use Illuminate\Auth\Access\AuthorizationException;
class CancelCheckoutRequestAction
{
public static function run(Asset $asset, User $user)
{
if (!Company::isCurrentUserHasAccess($asset)) {
throw new AuthorizationException();
}
$asset->cancelRequest();
$asset->decrement('requests_counter', 1);
$data['item'] = $asset;
$data['target'] = $user;
$data['item_quantity'] = 1;
$settings = Setting::getSettings();
$logaction = new Actionlog();
$logaction->item_id = $data['asset_id'] = $asset->id;
$logaction->item_type = $data['item_type'] = Asset::class;
$logaction->created_at = $data['requested_date'] = date('Y-m-d H:i:s');
$logaction->target_id = $data['user_id'] = auth()->id();
$logaction->target_type = User::class;
$logaction->location_id = $user->location_id ?? null;
$logaction->logaction('request canceled');
try {
$settings->notify(new RequestAssetCancelation($data));
} catch (\Exception $e) {
\Log::warning($e);
}
return true;
}
}

View file

@ -0,0 +1,54 @@
<?php
namespace App\Actions\CheckoutRequests;
use App\Exceptions\AssetNotRequestable;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\Company;
use App\Models\Setting;
use App\Models\User;
use App\Notifications\RequestAssetNotification;
use Illuminate\Auth\Access\AuthorizationException;
use Log;
class CreateCheckoutRequestAction
{
/**
* @throws AssetNotRequestable
* @throws AuthorizationException
*/
public static function run(Asset $asset, User $user): string
{
if (is_null(Asset::RequestableAssets()->find($asset->id))) {
throw new AssetNotRequestable($asset);
}
if (!Company::isCurrentUserHasAccess($asset)) {
throw new AuthorizationException();
}
$data['item'] = $asset;
$data['target'] = $user;
$data['item_quantity'] = 1;
$settings = Setting::getSettings();
$logaction = new Actionlog();
$logaction->item_id = $data['asset_id'] = $asset->id;
$logaction->item_type = $data['item_type'] = Asset::class;
$logaction->created_at = $data['requested_date'] = date('Y-m-d H:i:s');
$logaction->target_id = $data['user_id'] = auth()->id();
$logaction->target_type = User::class;
$logaction->location_id = $user->location_id ?? null;
$logaction->logaction('requested');
$asset->request();
$asset->increment('requests_counter', 1);
try {
$settings->notify(new RequestAssetNotification($data));
} catch (\Exception $e) {
Log::warning($e);
}
return true;
}
}

View file

@ -49,6 +49,7 @@ class SendExpirationAlerts extends Command
// Send a rollup to the admin, if settings dictate
$recipients = collect(explode(',', $settings->alert_email))
->map(fn($item) => trim($item)) // Trim each email
->filter(fn($item) => !empty($item))
->all();
// Expiring Assets
$assets = Asset::getExpiringWarrantee($alert_interval);

View file

@ -55,6 +55,7 @@ class SendUpcomingAuditReport extends Command
// Send a rollup to the admin, if settings dictate
$recipients = collect(explode(',', $settings->alert_email))
->map(fn($item) => trim($item))
->filter(fn($item) => !empty($item))
->all();

View file

@ -0,0 +1,9 @@
<?php
namespace App\Exceptions;
use Exception;
class AssetNotRequestable extends Exception
{
}

View file

@ -141,6 +141,8 @@ class Handler extends ExceptionHandler
$route = 'kits.index';
} elseif ($route == 'assetmaintenances.index') {
$route = 'maintenances.index';
} elseif ($route === 'licenseseats.index') {
$route = 'licenses.index';
}
return redirect()
@ -203,4 +205,4 @@ class Handler extends ExceptionHandler
//
});
}
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace App\Exceptions;
use Exception;
class UserDoestExistException extends Exception
{
}

View file

@ -112,13 +112,13 @@ class AccessoriesController extends Controller
{
$this->authorize('create', Accessory::class);
$accessory = clone $accessory;
$accessory->id = null;
$accessory->location_id = null;
$cloned = clone $accessory;
$cloned->id = null;
$cloned->deleted_at = '';
$cloned->location_id = null;
return view('accessories/edit')
->with('item', $accessory);
->with('item', $cloned);
}

View file

@ -208,9 +208,12 @@ class AcceptanceController extends Controller
*/
$branding_settings = SettingsController::getPDFBranding();
if (is_null($branding_settings->logo)){
$path_logo = "";
} else {
$path_logo = "";
// Check for the PDF logo path and use that, otherwise use the regular logo path
if (!is_null($branding_settings->acceptance_pdf_logo)) {
$path_logo = public_path() . '/uploads/' . $branding_settings->acceptance_pdf_logo;
} elseif (!is_null($branding_settings->logo)) {
$path_logo = public_path() . '/uploads/' . $branding_settings->logo;
}

View file

@ -491,15 +491,32 @@ class AssetsController extends Controller
public function showBySerial(Request $request, $serial): JsonResponse | array
{
$this->authorize('index', Asset::class);
$assets = Asset::where('serial', $serial)->with('assetstatus')->with('assignedTo');
$assets = Asset::where('serial', $serial)->with([
'assetstatus',
'assignedTo',
'company',
'defaultLoc',
'location',
'model.category',
'model.depreciation',
'model.fieldset',
'model.manufacturer',
'supplier',
]);
// Check if they've passed ?deleted=true
if ($request->input('deleted', 'false') == 'true') {
$assets = $assets->withTrashed();
}
if (($assets = $assets->get()) && ($assets->count()) > 0) {
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
$offset = ($request->input('offset') > $assets->count()) ? $assets->count() : app('api_offset_value');
$limit = app('api_limit_value');
$total = $assets->count();
$assets = $assets->skip($offset)->take($limit)->get();
if (($assets) && ($assets->count()) > 0) {
return (new AssetsTransformer)->transformAssets($assets, $total);
}
// If there are 0 results, return the "no such asset" response

View file

@ -0,0 +1,44 @@
<?php
namespace App\Http\Controllers\Api;
use App\Actions\CheckoutRequests\CancelCheckoutRequestAction;
use App\Actions\CheckoutRequests\CreateCheckoutRequestAction;
use App\Exceptions\AssetNotRequestable;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Models\Asset;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Http\JsonResponse;
use Exception;
class CheckoutRequest extends Controller
{
public function store(Asset $asset): JsonResponse
{
try {
CreateCheckoutRequestAction::run($asset, auth()->user());
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/hardware/message.requests.success')));
} catch (AssetNotRequestable $e) {
return response()->json(Helper::formatStandardApiResponse('error', 'Asset is not requestable'));
} catch (AuthorizationException $e) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.insufficient_permissions')));
} catch (Exception $e) {
report($e);
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.something_went_wrong')));
}
}
public function destroy(Asset $asset): JsonResponse
{
try {
CancelCheckoutRequestAction::run($asset, auth()->user());
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/hardware/message.requests.canceled')));
} catch (AuthorizationException $e) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.insufficient_permissions')));
} catch (Exception $e) {
report($e);
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.something_went_wrong')));
}
}
}

View file

@ -117,7 +117,7 @@ class AssetMaintenancesController extends Controller
) {
$startDate = Carbon::parse($assetMaintenance->start_date);
$completionDate = Carbon::parse($assetMaintenance->completion_date);
$assetMaintenance->asset_maintenance_time = $completionDate->diffInDays($startDate);
$assetMaintenance->asset_maintenance_time = (int) $completionDate->diffInDays($startDate, true);
}
// Was the asset maintenance created?
@ -210,7 +210,7 @@ class AssetMaintenancesController extends Controller
) {
$startDate = Carbon::parse($maintenance->start_date);
$completionDate = Carbon::parse($maintenance->completion_date);
$maintenance->asset_maintenance_time = $completionDate->diffInDays($startDate);
$maintenance->asset_maintenance_time = (int) $completionDate->diffInDays($startDate, true);
}
// Was the asset maintenance created?

View file

@ -318,7 +318,7 @@ class AssetsController extends Controller
$asset->eol_explicit = false;
} elseif ($request->filled('asset_eol_date')) {
$asset->asset_eol_date = $request->input('asset_eol_date', null);
$months = Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date);
$months = (int) Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date, true);
if($asset->model->eol) {
if($months != $asset->model->eol > 0) {
$asset->eol_explicit = true;

View file

@ -570,7 +570,6 @@ class BulkAssetsController extends Controller
*/
public function storeCheckout(AssetCheckoutRequest $request) : RedirectResponse | ModelNotFoundException
{
$this->authorize('checkout', Asset::class);
try {
@ -584,6 +583,8 @@ class BulkAssetsController extends Controller
$asset_ids = array_filter($request->get('selected_assets'));
$assets = Asset::findOrFail($asset_ids);
if (request('checkout_to_type') == 'asset') {
foreach ($asset_ids as $asset_id) {
if ($target->id == $asset_id) {
@ -603,9 +604,8 @@ class BulkAssetsController extends Controller
}
$errors = [];
DB::transaction(function () use ($target, $admin, $checkout_at, $expected_checkin, &$errors, $asset_ids, $request) { //NOTE: $errors is passsed by reference!
foreach ($asset_ids as $asset_id) {
$asset = Asset::findOrFail($asset_id);
DB::transaction(function () use ($target, $admin, $checkout_at, $expected_checkin, &$errors, $assets, $request) { //NOTE: $errors is passsed by reference!
foreach ($assets as $asset) {
$this->authorize('checkout', $asset);
$checkout_success = $asset->checkOut($target, $admin, $checkout_at, $expected_checkin, e($request->get('note')), $asset->name, null);
@ -632,7 +632,7 @@ class BulkAssetsController extends Controller
// Redirect to the asset management page with error
return redirect()->route('hardware.bulkcheckout.show')->withInput()->with('error', trans_choice('admin/hardware/message.multi-checkout.error', $asset_ids))->withErrors($errors);
} catch (ModelNotFoundException $e) {
return redirect()->route('hardware.bulkcheckout.show')->with('error', $e->getErrors());
return redirect()->route('hardware.bulkcheckout.show')->withInput()->with('error', trans_choice('admin/hardware/message.multi-checkout.error', $request->input('selected_assets')));
}
}

View file

@ -284,8 +284,11 @@ class LoginController extends Controller
return redirect()->back()->withInput()->withErrors($validator);
}
$this->maxLoginAttempts = config('auth.passwords.users.throttle.max_attempts');
$this->lockoutTime = config('auth.passwords.users.throttle.lockout_duration');
// Set the custom lockout attempts from the env and sett the custom lockout throttle from the env.
// We divide decayMinutes by 60 here to get minutes, since Laravel changed the default from minutes
// to seconds, and we don't want to break limits on existing systems
$this->maxAttempts = config('auth.passwords.users.throttle.max_attempts');
$this->decayMinutes = (config('auth.passwords.users.throttle.lockout_duration') / 60);
if ($lockedOut = $this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
@ -355,7 +358,7 @@ class LoginController extends Controller
// We wouldn't normally see this page if 2FA isn't enforced via the
// \App\Http\Middleware\CheckForTwoFactor middleware AND if a device isn't enrolled,
// but let's check check anyway in case there's a browser history or back button thing.
// but let's check anyway in case there's a browser history or back button thing.
// While you can access this page directly, enrolling a device when 2FA isn't enforced
// won't cause any harm.
@ -521,45 +524,6 @@ class LoginController extends Controller
return 'username';
}
/**
* Redirect the user after determining they are locked out.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*/
protected function sendLockoutResponse(Request $request)
{
$seconds = $this->limiter()->availableIn(
$this->throttleKey($request)
);
$minutes = round($seconds / 60);
$message = trans('auth/message.throttle', ['minutes' => $minutes]);
return redirect()->back()
->withInput($request->only($this->username(), 'remember'))
->withErrors([$this->username() => $message]);
}
/**
* Override the lockout time and duration
*
* @param \Illuminate\Http\Request $request
* @return bool
*/
protected function hasTooManyLoginAttempts(Request $request)
{
$lockoutTime = config('auth.passwords.users.throttle.lockout_duration');
$maxLoginAttempts = config('auth.passwords.users.throttle.max_attempts');
return $this->limiter()->tooManyAttempts(
$this->throttleKey($request),
$maxLoginAttempts,
$lockoutTime
);
}
public function legacyAuthRedirect()
{

View file

@ -41,10 +41,11 @@ class ModalController extends Controller
$view = view("modals.${type}");
if ($type == "statuslabel") {
$view->with('statuslabel_types', Helper::statusTypeList());
}
if (in_array($type, ['kit-model', 'kit-license', 'kit-consumable', 'kit-accessory'])) {
$view->with('kitId', $itemId);
$view->with('statuslabel_types', Helper::statusTypeList());
}
if (in_array($type, ['kit-model', 'kit-license', 'kit-consumable', 'kit-accessory'])) {
$view->with('kitId', $itemId);
}
return $view;
}

View file

@ -493,6 +493,17 @@ class ReportsController extends Controller
$header[] = trans('admin/hardware/table.eol');
}
if ($request->filled('warranty')) {
$header[] = trans('admin/hardware/form.warranty');
$header[] = trans('admin/hardware/form.warranty_expires');
}
if ($request->filled('depreciation')) {
$header[] = trans('admin/hardware/table.book_value');
$header[] = trans('admin/hardware/table.diff');
$header[] = trans('admin/hardware/form.fully_depreciated');
}
if ($request->filled('order')) {
$header[] = trans('admin/hardware/form.order');
}
@ -579,17 +590,6 @@ class ReportsController extends Controller
$header[] = trans('general.status');
}
if ($request->filled('warranty')) {
$header[] = trans('admin/hardware/form.warranty');
$header[] = trans('admin/hardware/form.warranty_expires');
}
if ($request->filled('depreciation')) {
$header[] = trans('admin/hardware/table.book_value');
$header[] = trans('admin/hardware/table.diff');
$header[] = trans('admin/hardware/form.fully_depreciated');
}
if ($request->filled('checkout_date')) {
$header[] = trans('admin/hardware/table.checkout_date');
}
@ -805,6 +805,19 @@ class ReportsController extends Controller
$row[] = ($asset->purchase_date != '') ? $asset->asset_eol_date : '';
}
if ($request->filled('warranty')) {
$row[] = ($asset->warranty_months) ? $asset->warranty_months : '';
$row[] = $asset->present()->warranty_expires();
}
if ($request->filled('depreciation')) {
$depreciation = $asset->getDepreciatedValue();
$diff = ($asset->purchase_cost - $depreciation);
$row[] = Helper::formatCurrencyOutput($depreciation);
$row[] = Helper::formatCurrencyOutput($diff);
$row[] = (($asset->depreciation) && ($asset->depreciated_date())) ? $asset->depreciated_date()->format('Y-m-d') : '';
}
if ($request->filled('order')) {
$row[] = ($asset->order_number) ? $asset->order_number : '';
}
@ -938,19 +951,6 @@ class ReportsController extends Controller
$row[] = ($asset->assetstatus) ? $asset->assetstatus->name.' ('.$asset->present()->statusMeta.')' : '';
}
if ($request->filled('warranty')) {
$row[] = ($asset->warranty_months) ? $asset->warranty_months : '';
$row[] = $asset->present()->warranty_expires();
}
if ($request->filled('depreciation')) {
$depreciation = $asset->getDepreciatedValue();
$diff = ($asset->purchase_cost - $depreciation);
$row[] = Helper::formatCurrencyOutput($depreciation);
$row[] = Helper::formatCurrencyOutput($diff);
$row[] = (($asset->depreciation) && ($asset->depreciated_date())) ? $asset->depreciated_date()->format('Y-m-d') : '';
}
if ($request->filled('checkout_date')) {
$row[] = ($asset->last_checkout) ? $asset->last_checkout : '';
}
@ -1081,10 +1081,10 @@ class ReportsController extends Controller
$row[] = e($assetMaintenance->start_date);
$row[] = e($assetMaintenance->completion_date);
if (is_null($assetMaintenance->asset_maintenance_time)) {
$improvementTime = intval(Carbon::now()
->diffInDays(Carbon::parse($assetMaintenance->start_date)));
$improvementTime = (int) Carbon::now()
->diffInDays(Carbon::parse($assetMaintenance->start_date), true);
} else {
$improvementTime = intval($assetMaintenance->asset_maintenance_time);
$improvementTime = (int) $assetMaintenance->asset_maintenance_time;
}
$row[] = $improvementTime;
$row[] = trans('general.currency') . Helper::formatCurrencyOutput($assetMaintenance->cost);

View file

@ -428,6 +428,13 @@ class SettingsController extends Controller
$setting->label_logo = null;
}
// Acceptance PDF upload
$setting = $request->handleImages($setting, 600, 'acceptance_pdf_logo', '', 'acceptance_pdf_logo');
if ('1' == $request->input('clear_acceptance_pdf_logo')) {
$setting = $request->deleteExistingImage($setting, '', 'acceptance_pdf_logo');
$setting->acceptance_pdf_logo = null;
}
// Favicon upload
$setting = $request->handleImages($setting, 100, 'favicon', '', 'favicon');
if ('1' == $request->input('clear_favicon')) {
@ -435,6 +442,7 @@ class SettingsController extends Controller
$setting->favicon = null;
}
// Default avatar upload
$setting = $request->handleImages($setting, 500, 'default_avatar', 'avatars', 'default_avatar');
if ($request->input('clear_default_avatar') == '1') {

View file

@ -360,7 +360,7 @@ class BulkUsersController extends Controller
$logAction->item_type = Accessory::class;
$logAction->target_id = $accessoryUserRow->assigned_to;
$logAction->target_type = User::class;
$logAction->created_at = auth()->id();
$logAction->created_by = auth()->id();
$logAction->note = 'Bulk checkin items';
$logAction->logaction('checkin from');
}
@ -374,7 +374,7 @@ class BulkUsersController extends Controller
$logAction->item_type = Consumable::class;
$logAction->target_id = $consumableUserRow->assigned_to;
$logAction->target_type = User::class;
$logAction->created_at = auth()->id();
$logAction->created_by = auth()->id();
$logAction->note = 'Bulk checkin items';
$logAction->logaction('checkin from');
}

View file

@ -395,13 +395,22 @@ class UsersController extends Controller
// Make sure the user can view users at all
$this->authorize('view', User::class);
$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($user->id);
$user = User::with([
'consumables',
'accessories',
'licenses',
'userloc',
])
->withTrashed()
->find($user->id);
// Make sure they can view this particular user
$this->authorize('view', $user);
$userlog = $user->userlog->load('item');
return view('users/view', compact('user', 'userlog'))->with('settings', Setting::getSettings());
return view('users/view', [
'user' => $user,
'settings' => Setting::getSettings(),
]);
}

View file

@ -2,18 +2,21 @@
namespace App\Http\Controllers;
use App\Actions\CheckoutRequests\CancelCheckoutRequestAction;
use App\Actions\CheckoutRequests\CreateCheckoutRequestAction;
use App\Exceptions\AssetNotRequestable;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\AssetModel;
use App\Models\Company;
use App\Models\Setting;
use App\Models\User;
use App\Notifications\RequestAssetCancelation;
use App\Notifications\RequestAssetNotification;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use \Illuminate\Contracts\View\View;
use Log;
use Exception;
/**
* This controller handles all actions related to the ability for users
@ -81,7 +84,7 @@ class ViewAssetsController extends Controller
return view('account/requestable-assets', compact('assets', 'models'));
}
public function getRequestItem(Request $request, $itemType, $itemId = null, $cancel_by_admin = false, $requestingUser = null) : RedirectResponse
public function getRequestItem(Request $request, $itemType, $itemId = null, $cancel_by_admin = false, $requestingUser = null): RedirectResponse
{
$item = null;
$fullItemType = 'App\\Models\\'.studly_case($itemType);
@ -144,63 +147,33 @@ class ViewAssetsController extends Controller
* Process a specific requested asset
* @param null $assetId
*/
public function getRequestAsset($assetId = null) : RedirectResponse
public function store(Asset $asset): RedirectResponse
{
$user = auth()->user();
// Check if the asset exists and is requestable
if (is_null($asset = Asset::RequestableAssets()->find($assetId))) {
return redirect()->route('requestable-assets')
->with('error', trans('admin/hardware/message.does_not_exist_or_not_requestable'));
}
if (! Company::isCurrentUserHasAccess($asset)) {
return redirect()->route('requestable-assets')
->with('error', trans('general.insufficient_permissions'));
}
$data['item'] = $asset;
$data['target'] = auth()->user();
$data['item_quantity'] = 1;
$settings = Setting::getSettings();
$logaction = new Actionlog();
$logaction->item_id = $data['asset_id'] = $asset->id;
$logaction->item_type = $data['item_type'] = Asset::class;
$logaction->created_at = $data['requested_date'] = date('Y-m-d H:i:s');
if ($user->location_id) {
$logaction->location_id = $user->location_id;
}
$logaction->target_id = $data['user_id'] = auth()->id();
$logaction->target_type = User::class;
// If it's already requested, cancel the request.
if ($asset->isRequestedBy(auth()->user())) {
$asset->cancelRequest();
$asset->decrement('requests_counter', 1);
$logaction->logaction('request canceled');
try {
$settings->notify(new RequestAssetCancelation($data));
} catch (\Exception $e) {
Log::warning($e);
}
return redirect()->route('requestable-assets')
->with('success')->with('success', trans('admin/hardware/message.requests.canceled'));
}
$logaction->logaction('requested');
$asset->request();
$asset->increment('requests_counter', 1);
try {
$settings->notify(new RequestAssetNotification($data));
} catch (\Exception $e) {
Log::warning($e);
CreateCheckoutRequestAction::run($asset, auth()->user());
return redirect()->route('requestable-assets')->with('success')->with('success', trans('admin/hardware/message.requests.success'));
} catch (AssetNotRequestable $e) {
return redirect()->back()->with('error', 'Asset is not requestable');
} catch (AuthorizationException $e) {
return redirect()->back()->with('error', trans('admin/hardware/message.requests.error'));
} catch (Exception $e) {
report($e);
return redirect()->back()->with('error', trans('general.something_went_wrong'));
}
return redirect()->route('requestable-assets')->with('success')->with('success', trans('admin/hardware/message.requests.success'));
}
public function destroy(Asset $asset): RedirectResponse
{
try {
CancelCheckoutRequestAction::run($asset, auth()->user());
return redirect()->route('requestable-assets')->with('success')->with('success', trans('admin/hardware/message.requests.canceled'));
} catch (Exception $e) {
report($e);
return redirect()->back()->with('error', trans('general.something_went_wrong'));
}
}
public function getRequestedAssets() : View
{
return view('account/requested');

View file

@ -29,6 +29,12 @@ class StoreLabelSettings extends FormRequest
return $label->getName();
})->values()->toArray();
if (empty($this->input('label2_template'))) {
$this->merge([
'label2_template' => 'DefaultLabel',
]);
}
return [
'labels_per_page' => 'numeric',
'labels_width' => 'numeric',

View file

@ -37,8 +37,10 @@ class AccessoriesTransformer
'purchase_date' => ($accessory->purchase_date) ? Helper::getFormattedDateObject($accessory->purchase_date, 'date') : null,
'purchase_cost' => Helper::formatCurrencyOutput($accessory->purchase_cost),
'order_number' => ($accessory->order_number) ? e($accessory->order_number) : null,
'min_qty' => ($accessory->min_amt) ? (int) $accessory->min_amt : null,
'remaining_qty' => (int) ($accessory->qty - $accessory->checkouts_count),
'min_qty' => ($accessory->min_amt) ? (int) $accessory->min_amt : null, // Legacy - should phase out - replaced by below, for the bootstrap table formatter
'min_amt' => ($accessory->min_amt) ? (int) $accessory->min_amt : null,
'remaining_qty' => (int) ($accessory->qty - $accessory->checkouts_count), // Legacy - should phase out - replaced by below, for the bootstrap table formatter
'remaining' => (int) ($accessory->qty - $accessory->checkouts_count),
'checkouts_count' => $accessory->checkouts_count,
'created_by' => ($accessory->adminuser) ? [
'id' => (int) $accessory->adminuser->id,

View file

@ -46,8 +46,9 @@ class AssetModelsTransformer
'name'=> e($assetmodel->manufacturer->name),
] : null,
'image' => ($assetmodel->image != '') ? Storage::disk('public')->url('models/'.e($assetmodel->image)) : null,
'model_number' => e($assetmodel->model_number),
'model_number' => ($assetmodel->model_number ? e($assetmodel->model_number): null),
'min_amt' => ($assetmodel->min_amt) ? (int) $assetmodel->min_amt : null,
'remaining' => (int) ($assetmodel->assets_count - $assetmodel->min_amt),
'depreciation' => ($assetmodel->depreciation) ? [
'id' => (int) $assetmodel->depreciation->id,
'name'=> e($assetmodel->depreciation->name),

View file

@ -42,7 +42,7 @@ class AssetsTransformer
'requestable' => ($asset->requestable ? true : false),
'model_number' => (($asset->model) && ($asset->model->model_number)) ? e($asset->model->model_number) : null,
'eol' => (($asset->asset_eol_date != '') && ($asset->purchase_date != '')) ? Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date).' months' : null,
'eol' => (($asset->asset_eol_date != '') && ($asset->purchase_date != '')) ? (int) Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date, true) . ' months' : null,
'asset_eol_date' => ($asset->asset_eol_date != '') ? Helper::getFormattedDateObject($asset->asset_eol_date, 'date') : null,
'status_label' => ($asset->assetstatus) ? [
'id' => (int) $asset->assetstatus->id,

View file

@ -38,6 +38,7 @@ class LicensesTransformer
'expiration_date' => Helper::getFormattedDateObject($license->expiration_date, 'date'),
'seats' => (int) $license->seats,
'free_seats_count' => (int) $license->free_seats_count,
'remaining' => (int) $license->free_seats_count,
'min_amt' => ($license->min_amt) ? (int) ($license->min_amt) : null,
'license_name' => ($license->license_name) ? e($license->license_name) : null,
'license_email' => ($license->license_email) ? e($license->license_email) : null,

View file

@ -101,11 +101,8 @@ class LocationsTransformer
$array = [
'id' => $accessory_checkout->id,
'assigned_to' => $accessory_checkout->assigned_to,
'accessory' => [
'id' => $accessory_checkout->accessory->id,
'name' => $accessory_checkout->accessory->name,
],
'image' => ($accessory_checkout->accessory->image) ? Storage::disk('public')->url('accessories/'.e($accessory_checkout->accessory->image)) : null,
'accessory' => $this->transformAccessory($accessory_checkout->accessory),
'image' => ($accessory_checkout?->accessory?->image) ? Storage::disk('public')->url('accessories/' . e($accessory_checkout->accessory->image)) : null,
'note' => $accessory_checkout->note ? e($accessory_checkout->note) : null,
'created_by' => $accessory_checkout->adminuser ? [
'id' => (int) $accessory_checkout->adminuser->id,
@ -153,4 +150,16 @@ class LocationsTransformer
return $array;
}
}
}
private function transformAccessory(?Accessory $accessory): ?array
{
if ($accessory) {
return [
'id' => $accessory->id,
'name' => $accessory->name,
];
}
return null;
}
}

View file

@ -295,13 +295,13 @@ class Actionlog extends SnipeModel
$now = Carbon::now();
$last_audit_date = $this->created_at; // this is the action log's created at, not the asset itself
$next_audit = $last_audit_date->addMonth($monthInterval); // this actually *modifies* the $last_audit_date
$next_audit_days = round($now->diffInDays($next_audit, true));
$next_audit_days = (int) round($now->diffInDays($next_audit, true));
$override_default_next = $next_audit;
// Override the default setting for interval if the asset has its own next audit date
if (($asset) && ($asset->next_audit_date)) {
$override_default_next = Carbon::parse($asset->next_audit_date);
$next_audit_days = round($override_default_next->diffInDays($now, true));
$next_audit_days = (int) round($override_default_next->diffInDays($now, true));
}
// Show as negative number if the next audit date is before the audit date we're looking at

View file

@ -1456,7 +1456,7 @@ class Asset extends Depreciable
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeRequestableAssets($query)
public function scopeRequestableAssets($query): Builder
{
$table = $query->getModel()->getTable();

View file

@ -67,7 +67,8 @@ final class Company extends SnipeModel
'phone',
'fax',
'email',
'created_by'
'created_by',
'notes',
];
private static function isFullMultipleCompanySupportEnabled()

View file

@ -0,0 +1,84 @@
<?php
namespace App\Models\Labels\Sheets\Avery;
class _5520_B extends _5520
{
private const BARCODE_SIZE = 0.20;
private const BARCODE_MARGIN = 1.40;
private const TAG_SIZE = 0.125;
private const TITLE_SIZE = 0.140;
private const TITLE_MARGIN = 0.025;
private const LABEL_SIZE = 0.090;
private const LABEL_MARGIN = -0.015;
private const FIELD_SIZE = 0.150;
private const FIELD_MARGIN = 0.012;
public function getUnit() { return 'in'; }
public function getLabelMarginTop() { return 0.06; }
public function getLabelMarginBottom() { return 0.06; }
public function getLabelMarginLeft() { return 0.06; }
public function getLabelMarginRight() { return 0.06; }
public function getSupportAssetTag() { return false; }
public function getSupport1DBarcode() { return true; }
public function getSupport2DBarcode() { return false; }
public function getSupportFields() { return 2; }
public function getSupportLogo() { return false; }
public function getSupportTitle() { return true; }
public function preparePDF($pdf) {}
public function write($pdf, $record) {
$pa = $this->getLabelPrintableArea();
$currentX = $pa->x1;
$currentY = $pa->y1;
$usableWidth = $pa->w;
$usableHeight = $pa->h;
if ($record->has('title')) {
static::writeText(
$pdf, $record->get('title'),
$pa->x1, $pa->y1,
'freesans', '', self::TITLE_SIZE, 'C',
$pa->w, self::TITLE_SIZE, true, 0
);
$currentY += self::TITLE_SIZE + self::TITLE_MARGIN;
$usableHeight -= self::TITLE_SIZE + self::TITLE_MARGIN;
}
if ($record->has('barcode1d')) {
static::write1DBarcode(
$pdf, $record->get('barcode1d')->content, $record->get('barcode1d')->type,
$pa->x1, $pa->y2 - self::BARCODE_SIZE,
$usableWidth, self::BARCODE_SIZE
);
$usableHeight -= self::BARCODE_SIZE + self::BARCODE_MARGIN;
}
foreach ($record->get('fields') as $field) {
static::writeText(
$pdf, $field['label'],
$currentX, $currentY,
'freesans', '', self::LABEL_SIZE, 'L',
$usableWidth, self::LABEL_SIZE, true, 0
);
$currentY += self::LABEL_SIZE + self::LABEL_MARGIN;
static::writeText(
$pdf, $field['value'],
$currentX, $currentY,
'freemono', 'B', self::FIELD_SIZE, 'L',
$usableWidth, self::FIELD_SIZE, true, 0, 0.01
);
$currentY += self::FIELD_SIZE + self::FIELD_MARGIN;
}
}
}
?>

View file

@ -171,7 +171,7 @@ class AssetObserver
// determine if explicit and set eol_explicit to true
if (!is_null($asset->asset_eol_date) && !is_null($asset->purchase_date)) {
if($asset->model->eol > 0) {
$months = Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date);
$months = (int) Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date, true);
if($months != $asset->model->eol) {
$asset->eol_explicit = true;
}

View file

@ -78,28 +78,36 @@ class AccessoryPresenter extends Presenter
'sortable' => true,
'title' => trans('general.location'),
'formatter' => 'locationsLinkObjFormatter',
], [
'field' => 'min_amt',
'searchable' => false,
'sortable' => true,
'title' => trans('general.min_amt'),
'formatter' => 'minAmtFormatter',
'class' => 'text-right text-padding-number-cell',
], [
'field' => 'qty',
'searchable' => false,
'sortable' => true,
'title' => trans('admin/accessories/general.total'),
'footerFormatter' => 'qtySumFormatter',
'class' => 'text-right text-padding-number-cell',
], [
'field' => 'remaining_qty',
'field' => 'remaining',
'searchable' => false,
'sortable' => false,
'visible' => false,
'title' => trans('admin/accessories/general.remaining'),
'footerFormatter' => 'qtySumFormatter',
'class' => 'text-right text-padding-number-cell',
],[
'field' => 'checkouts_count',
'searchable' => false,
'sortable' => true,
'visible' => true,
'title' => trans('general.checked_out'),
], [
'field' => 'min_qty',
'searchable' => false,
'sortable' => true,
'title' => trans('general.min_amt'),
'footerFormatter' => 'qtySumFormatter',
'class' => 'text-right text-padding-number-cell',
], [
'field' => 'purchase_date',
'searchable' => true,
@ -113,7 +121,7 @@ class AccessoryPresenter extends Presenter
'sortable' => true,
'title' => trans('general.purchase_cost'),
'footerFormatter' => 'sumFormatterQuantity',
'class' => 'text-right',
'class' => 'text-right text-padding-number-cell',
], [
'field' => 'order_number',
'searchable' => true,

View file

@ -74,7 +74,10 @@ class AssetModelPresenter extends Presenter
'switchable' => true,
'title' => trans('mail.min_QTY'),
'visible' => true,
'formatter' => 'minAmtFormatter',
'class' => 'text-right text-padding-number-cell',
],
[
'field' => 'assets_count',
'searchable' => false,
@ -82,6 +85,19 @@ class AssetModelPresenter extends Presenter
'switchable' => true,
'title' => trans('admin/models/table.numassets'),
'visible' => true,
'class' => 'text-right text-padding-number-cell',
'footerFormatter' => 'qtySumFormatter',
],
[
'field' => 'remaining',
'searchable' => false,
'sortable' => false,
'switchable' => true,
'title' => trans('general.remaining'),
'visible' => true,
'class' => 'text-right text-padding-number-cell',
'footerFormatter' => 'qtySumFormatter',
],
[
'field' => 'depreciation',

View file

@ -79,24 +79,30 @@ class ComponentPresenter extends Presenter
'title' => trans('general.manufacturer'),
'visible' => false,
'formatter' => 'manufacturersLinkObjFormatter',
], [
'field' => 'min_amt',
'searchable' => false,
'sortable' => true,
'title' => trans('general.min_amt'),
'visible' => true,
'class' => 'text-right text-padding-number-cell',
'formatter' => 'minAmtFormatter',
], [
'field' => 'qty',
'searchable' => false,
'sortable' => true,
'title' => trans('admin/components/general.total'),
'visible' => true,
'class' => 'text-right text-padding-number-cell',
'footerFormatter' => 'qtySumFormatter',
], [
'field' => 'remaining',
'searchable' => false,
'sortable' => false,
'title' => trans('admin/components/general.remaining'),
'visible' => true,
], [
'field' => 'min_amt',
'searchable' => false,
'sortable' => false,
'title' => trans('general.min_amt'),
'visible' => true,
'class' => 'text-right text-padding-number-cell',
'footerFormatter' => 'qtySumFormatter',
], [
'field' => 'location',
'searchable' => true,

View file

@ -72,25 +72,31 @@ class ConsumablePresenter extends Presenter
'searchable' => true,
'sortable' => true,
'title' => trans('admin/consumables/general.item_no'),
], [
'field' => 'min_amt',
'searchable' => false,
'sortable' => true,
'title' => trans('general.min_amt'),
'visible' => true,
'formatter' => 'minAmtFormatter',
'class' => 'text-right text-padding-number-cell',
], [
'field' => 'qty',
'searchable' => false,
'sortable' => true,
'title' => trans('admin/components/general.total'),
'visible' => true,
'class' => 'text-right text-padding-number-cell',
'footerFormatter' => 'qtySumFormatter',
], [
'field' => 'remaining',
'searchable' => false,
'sortable' => true,
'title' => trans('admin/components/general.remaining'),
'visible' => true,
'class' => 'text-right text-padding-number-cell',
'footerFormatter' => 'qtySumFormatter',
], [
'field' => 'min_amt',
'searchable' => false,
'sortable' => false,
'title' => trans('general.min_amt'),
'visible' => true,
], [
'field' => 'location',
'searchable' => true,
'sortable' => true,
@ -123,7 +129,7 @@ class ConsumablePresenter extends Presenter
'title' => trans('general.purchase_cost'),
'visible' => true,
'footerFormatter' => 'sumFormatterQuantity',
'class' => 'text-right',
'class' => 'text-right text-padding-number-cell',
], [
'field' => 'notes',
'searchable' => true,

View file

@ -80,24 +80,28 @@ class LicensePresenter extends Presenter
'sortable' => true,
'title' => trans('general.manufacturer'),
'formatter' => 'manufacturersLinkObjFormatter',
], [
'field' => 'seats',
'searchable' => false,
'sortable' => true,
'title' => trans('admin/accessories/general.total'),
], [
'field' => 'free_seats_count',
'searchable' => false,
'sortable' => true,
'title' => trans('admin/accessories/general.remaining'),
],
[
], [
'field' => 'min_amt',
'searchable' => false,
'sortable' => true,
'title' => trans('mail.min_QTY'),
'formatter' => 'minAmtFormatter',
],[
'class' => 'text-right text-padding-number-cell',
], [
'field' => 'seats',
'searchable' => false,
'sortable' => true,
'title' => trans('admin/accessories/general.total'),
'class' => 'text-right text-padding-number-cell',
'footerFormatter' => 'qtySumFormatter',
], [
'field' => 'free_seats_count',
'searchable' => false,
'sortable' => true,
'title' => trans('admin/accessories/general.remaining'),
'class' => 'text-right text-padding-number-cell',
'footerFormatter' => 'qtySumFormatter',
], [
'field' => 'purchase_date',
'searchable' => true,
'sortable' => true,

63
composer.lock generated
View file

@ -2677,16 +2677,16 @@
},
{
"name": "laravel/framework",
"version": "v11.38.2",
"version": "v11.44.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "9d290aa90fcad44048bedca5219d2b872e98772a"
"reference": "0883d4175f4e2b5c299e7087ad3c74f2ce195c6d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/9d290aa90fcad44048bedca5219d2b872e98772a",
"reference": "9d290aa90fcad44048bedca5219d2b872e98772a",
"url": "https://api.github.com/repos/laravel/framework/zipball/0883d4175f4e2b5c299e7087ad3c74f2ce195c6d",
"reference": "0883d4175f4e2b5c299e7087ad3c74f2ce195c6d",
"shasum": ""
},
"require": {
@ -2712,7 +2712,7 @@
"league/flysystem-local": "^3.25.1",
"league/uri": "^7.5.1",
"monolog/monolog": "^3.0",
"nesbot/carbon": "^2.72.2|^3.4",
"nesbot/carbon": "^2.72.6|^3.8.4",
"nunomaduro/termwind": "^2.0",
"php": "^8.2",
"psr/container": "^1.1.1|^2.0.1",
@ -2787,17 +2787,18 @@
"fakerphp/faker": "^1.24",
"guzzlehttp/promises": "^2.0.3",
"guzzlehttp/psr7": "^2.4",
"laravel/pint": "^1.18",
"league/flysystem-aws-s3-v3": "^3.25.1",
"league/flysystem-ftp": "^3.25.1",
"league/flysystem-path-prefixing": "^3.25.1",
"league/flysystem-read-only": "^3.25.1",
"league/flysystem-sftp-v3": "^3.25.1",
"mockery/mockery": "^1.6.10",
"orchestra/testbench-core": "^9.6",
"orchestra/testbench-core": "^9.11.2",
"pda/pheanstalk": "^5.0.6",
"php-http/discovery": "^1.15",
"phpstan/phpstan": "^1.11.5",
"phpunit/phpunit": "^10.5.35|^11.3.6",
"phpstan/phpstan": "^2.0",
"phpunit/phpunit": "^10.5.35|^11.3.6|^12.0.1",
"predis/predis": "^2.3",
"resend/resend-php": "^0.10.0",
"symfony/cache": "^7.0.3",
@ -2829,7 +2830,7 @@
"mockery/mockery": "Required to use mocking (^1.6).",
"pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).",
"php-http/discovery": "Required to use PSR-7 bridging features (^1.15).",
"phpunit/phpunit": "Required to use assertions and run tests (^10.5|^11.0).",
"phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.3.6|^12.0.1).",
"predis/predis": "Required to use the predis connector (^2.3).",
"psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).",
"pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).",
@ -2887,7 +2888,7 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2025-01-15T00:06:46+00:00"
"time": "2025-03-05T15:34:10+00:00"
},
{
"name": "laravel/helpers",
@ -4678,16 +4679,16 @@
},
{
"name": "monolog/monolog",
"version": "3.8.1",
"version": "3.9.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
"reference": "aef6ee73a77a66e404dd6540934a9ef1b3c855b4"
"reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/aef6ee73a77a66e404dd6540934a9ef1b3c855b4",
"reference": "aef6ee73a77a66e404dd6540934a9ef1b3c855b4",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6",
"reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6",
"shasum": ""
},
"require": {
@ -4765,7 +4766,7 @@
],
"support": {
"issues": "https://github.com/Seldaek/monolog/issues",
"source": "https://github.com/Seldaek/monolog/tree/3.8.1"
"source": "https://github.com/Seldaek/monolog/tree/3.9.0"
},
"funding": [
{
@ -4777,7 +4778,7 @@
"type": "tidelift"
}
],
"time": "2024-12-05T17:15:07+00:00"
"time": "2025-03-24T10:02:05+00:00"
},
{
"name": "mtdowling/jmespath.php",
@ -7478,22 +7479,22 @@
},
{
"name": "rollbar/rollbar",
"version": "v4.0.2",
"version": "v4.1.1",
"source": {
"type": "git",
"url": "https://github.com/rollbar/rollbar-php.git",
"reference": "6966a4c97c170298108f5e5b543c2710658f8fe0"
"reference": "146216bbfde503632c6969a7c334c8a63c98f50e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/rollbar/rollbar-php/zipball/6966a4c97c170298108f5e5b543c2710658f8fe0",
"reference": "6966a4c97c170298108f5e5b543c2710658f8fe0",
"url": "https://api.github.com/repos/rollbar/rollbar-php/zipball/146216bbfde503632c6969a7c334c8a63c98f50e",
"reference": "146216bbfde503632c6969a7c334c8a63c98f50e",
"shasum": ""
},
"require": {
"ext-curl": "*",
"monolog/monolog": "^2 || ^3",
"php": ">=8.0.0 <9.0",
"php": ">=8.1.0 <9.0",
"psr/log": "^1 || ^2 || ^3"
},
"require-dev": {
@ -7535,28 +7536,28 @@
"support": {
"email": "support@rollbar.com",
"issues": "https://github.com/rollbar/rollbar-php/issues",
"source": "https://github.com/rollbar/rollbar-php/tree/v4.0.2"
"source": "https://github.com/rollbar/rollbar-php/tree/v4.1.1"
},
"time": "2023-12-22T21:40:31+00:00"
"time": "2025-03-21T19:07:30+00:00"
},
{
"name": "rollbar/rollbar-laravel",
"version": "v8.0.1",
"version": "v8.1.2",
"source": {
"type": "git",
"url": "https://github.com/rollbar/rollbar-php-laravel.git",
"reference": "69ecc7c19b54b1d88bf8a2bdfa56277500cc41f6"
"reference": "fbe96ea28601294aa7dc41cd16db62cddddeb0c2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/rollbar/rollbar-php-laravel/zipball/69ecc7c19b54b1d88bf8a2bdfa56277500cc41f6",
"reference": "69ecc7c19b54b1d88bf8a2bdfa56277500cc41f6",
"url": "https://api.github.com/repos/rollbar/rollbar-php-laravel/zipball/fbe96ea28601294aa7dc41cd16db62cddddeb0c2",
"reference": "fbe96ea28601294aa7dc41cd16db62cddddeb0c2",
"shasum": ""
},
"require": {
"illuminate/support": "^10.0|^11.0",
"illuminate/support": "^10.0|^11.0|^12.0",
"php": "^8.1",
"rollbar/rollbar": "^4.0"
"rollbar/rollbar": "v4.1.1"
},
"require-dev": {
"mockery/mockery": "^1",
@ -7607,9 +7608,9 @@
],
"support": {
"issues": "https://github.com/rollbar/rollbar-php-laravel/issues",
"source": "https://github.com/rollbar/rollbar-php-laravel/tree/v8.0.1"
"source": "https://github.com/rollbar/rollbar-php-laravel/tree/v8.1.2"
},
"time": "2024-02-13T21:58:17+00:00"
"time": "2025-03-21T19:26:39+00:00"
},
{
"name": "sabberworm/php-css-parser",

View file

@ -8,6 +8,22 @@
| be modified directly.
*/
// This is used by the mysql dump options in spatie backup
$dump_options = [
'dump_binary_path' => env('DB_DUMP_PATH', '/usr/local/bin'), // only the path, so without 'mysqldump'
'use_single_transaction' => false,
'timeout' => 60 * 5, // 5 minute timeout
//'exclude_tables' => ['table1', 'table2'],
//'add_extra_option' => '--optionname=optionvalue',
];
// Some versions of mysql do not support the --skip-ssl option and will fail if it is
if (env('DB_DUMP_SKIP_SSL') == 'true') {
$dump_options['skip_ssl'] = true;
}
return [
/*
@ -79,14 +95,7 @@ return [
'strict' => false,
'engine' => 'InnoDB',
'unix_socket' => env('DB_SOCKET', ''),
'dump' => [
'dump_binary_path' => env('DB_DUMP_PATH', '/usr/local/bin'), // only the path, so without 'mysqldump'
'use_single_transaction' => false,
'timeout' => 60 * 5, // 5 minute timeout
//'exclude_tables' => ['table1', 'table2'],
//'add_extra_option' => '--optionname=optionvalue',
],
'dump' => $dump_options,
'dump_command_timeout' => 60 * 5, // 5 minute timeout
'dump_using_single_transaction' => true, // perform dump using a single transaction
'options' => (env('DB_SSL')) ? ((env('DB_SSL_IS_PAAS')) ? [

View file

@ -1,10 +1,10 @@
<?php
return array (
'app_version' => 'v8.0.4',
'full_app_version' => 'v8.0.4 - build 17196-gc29bdbdac',
'build_version' => '17196',
'full_app_version' => 'v8.0.4 - build 17333-gaf408bb45',
'build_version' => '17333',
'prerelease_version' => '',
'hash_version' => 'gc29bdbdac',
'full_hash' => 'v8.0.4-29-gc29bdbdac',
'hash_version' => 'gaf408bb45',
'full_hash' => 'v8.0.4-135-gaf408bb45',
'branch' => 'develop',
);

View file

@ -357,12 +357,22 @@ class AssetFactory extends Factory
public function requestable()
{
return $this->state(['requestable' => true]);
$id = Statuslabel::factory()->create([
'archived' => false,
'deployable' => true,
'pending' => true,
])->id;
return $this->state(['status_id' => $id, 'requestable' => true]);
}
public function nonrequestable()
{
return $this->state(['requestable' => false]);
$id = Statuslabel::factory()->create([
'archived' => true,
'deployable' => false,
'pending' => false,
])->id;
return $this->state(['status_id' => $id, 'requestable' => false]);
}
public function noPurchaseOrEolDate()

View file

@ -150,6 +150,11 @@ class UserFactory extends Factory
return $this->appendPermission(['models.delete' => '1']);
}
public function viewAssetModels()
{
return $this->appendPermission(['models.view' => '1']);
}
public function viewAccessories()
{
return $this->appendPermission(['accessories.view' => '1']);
@ -290,6 +295,11 @@ class UserFactory extends Factory
return $this->appendPermission(['companies.delete' => '1']);
}
public function editCompanies()
{
return $this->appendPermission(['companies.edit' => '1']);
}
public function viewUsers()
{
return $this->appendPermission(['users.view' => '1']);
@ -360,6 +370,11 @@ class UserFactory extends Factory
return $this->appendPermission(['kits.delete' => '1']);
}
public function viewPredefinedKits()
{
return $this->appendPermission(['kits.view' => '1']);
}
public function deleteStatusLabels()
{
return $this->appendPermission(['statuslabels.delete' => '1']);

View file

@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('settings', function (Blueprint $table) {
$table->char('acceptance_pdf_logo')->after('label_logo')->nullable()->default(null);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('settings', function (Blueprint $table) {
$table->dropColumn('acceptance_pdf_logo');
});
}
};

163
package-lock.json generated
View file

@ -6,7 +6,7 @@
"": {
"dependencies": {
"@fortawesome/fontawesome-free": "^6.7.2",
"acorn": "^8.12.0",
"acorn": "^8.14.1",
"acorn-import-assertions": "^1.9.0",
"admin-lte": "^2.4.18",
"ajv": "^6.12.6",
@ -15,7 +15,7 @@
"bootstrap-colorpicker": "^2.5.3",
"bootstrap-datepicker": "^1.10.0",
"bootstrap-less": "^3.3.8",
"bootstrap-table": "1.24.0",
"bootstrap-table": "1.24.1",
"canvas-confetti": "^1.9.3",
"chart.js": "^2.9.4",
"clipboard": "^2.0.11",
@ -37,7 +37,7 @@
"signature_pad": "^4.2.0",
"tableexport.jquery.plugin": "1.30.0",
"tether": "^1.4.0",
"webpack": "^5.97.1"
"webpack": "^5.98.0"
},
"devDependencies": {
"all-contributors-cli": "^6.26.1",
@ -2502,9 +2502,9 @@
}
},
"node_modules/acorn": {
"version": "8.14.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
"version": "8.14.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
"bin": {
"acorn": "bin/acorn"
},
@ -2605,7 +2605,6 @@
},
"node_modules/ajv-formats": {
"version": "2.1.1",
"dev": true,
"license": "MIT",
"dependencies": {
"ajv": "^8.0.0"
@ -2621,7 +2620,6 @@
},
"node_modules/ajv-formats/node_modules/ajv": {
"version": "8.13.0",
"dev": true,
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3",
@ -2636,7 +2634,6 @@
},
"node_modules/ajv-formats/node_modules/json-schema-traverse": {
"version": "1.0.0",
"dev": true,
"license": "MIT"
},
"node_modules/ajv-keywords": {
@ -3705,9 +3702,9 @@
"license": "MIT"
},
"node_modules/bootstrap-table": {
"version": "1.24.0",
"resolved": "https://registry.npmjs.org/bootstrap-table/-/bootstrap-table-1.24.0.tgz",
"integrity": "sha512-dyRf5PQwTgFHj9yjuPXa+GIf4JpuQhsgD1CJrOqhw40qI2gTb3mJfRdoBc7iF2bqzOl+k0RnbAlhSPbGe4VS+w==",
"version": "1.24.1",
"resolved": "https://registry.npmjs.org/bootstrap-table/-/bootstrap-table-1.24.1.tgz",
"integrity": "sha512-que7o2Z6R0I3cfwfm6qg4XnoUK9A/8162HUErFYg3fGtzjk5OjLJx6Ji9p3oKz+IAIVvBCr9sqMqujEG47k3zA==",
"peerDependencies": {
"jquery": "3"
}
@ -5628,6 +5625,21 @@
"version": "2.1.1",
"license": "MIT"
},
"node_modules/fast-uri": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz",
"integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
]
},
"node_modules/fastclick": {
"version": "1.0.6"
},
@ -9520,7 +9532,6 @@
},
"node_modules/require-from-string": {
"version": "2.0.2",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@ -10443,8 +10454,9 @@
}
},
"node_modules/terser": {
"version": "5.31.0",
"license": "BSD-2-Clause",
"version": "5.39.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz",
"integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==",
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
"acorn": "^8.8.2",
@ -10459,14 +10471,15 @@
}
},
"node_modules/terser-webpack-plugin": {
"version": "5.3.10",
"license": "MIT",
"version": "5.3.14",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz",
"integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==",
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.20",
"@jridgewell/trace-mapping": "^0.3.25",
"jest-worker": "^27.4.5",
"schema-utils": "^3.1.1",
"serialize-javascript": "^6.0.1",
"terser": "^5.26.0"
"schema-utils": "^4.3.0",
"serialize-javascript": "^6.0.2",
"terser": "^5.31.1"
},
"engines": {
"node": ">= 10.13.0"
@ -10490,6 +10503,55 @@
}
}
},
"node_modules/terser-webpack-plugin/node_modules/ajv": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/terser-webpack-plugin/node_modules/ajv-keywords": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
"integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
"dependencies": {
"fast-deep-equal": "^3.1.3"
},
"peerDependencies": {
"ajv": "^8.8.2"
}
},
"node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
},
"node_modules/terser-webpack-plugin/node_modules/schema-utils": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz",
"integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==",
"dependencies": {
"@types/json-schema": "^7.0.9",
"ajv": "^8.9.0",
"ajv-formats": "^2.1.1",
"ajv-keywords": "^5.1.0"
},
"engines": {
"node": ">= 10.13.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
}
},
"node_modules/terser/node_modules/commander": {
"version": "2.20.3",
"license": "MIT"
@ -10901,9 +10963,9 @@
"license": "BSD-2-Clause"
},
"node_modules/webpack": {
"version": "5.97.1",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz",
"integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==",
"version": "5.98.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.98.0.tgz",
"integrity": "sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA==",
"dependencies": {
"@types/eslint-scope": "^3.7.7",
"@types/estree": "^1.0.6",
@ -10923,9 +10985,9 @@
"loader-runner": "^4.2.0",
"mime-types": "^2.1.27",
"neo-async": "^2.6.2",
"schema-utils": "^3.2.0",
"schema-utils": "^4.3.0",
"tapable": "^2.1.1",
"terser-webpack-plugin": "^5.3.10",
"terser-webpack-plugin": "^5.3.11",
"watchpack": "^2.4.1",
"webpack-sources": "^3.2.3"
},
@ -11208,6 +11270,55 @@
"source-map": "~0.6.1"
}
},
"node_modules/webpack/node_modules/ajv": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/webpack/node_modules/ajv-keywords": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
"integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
"dependencies": {
"fast-deep-equal": "^3.1.3"
},
"peerDependencies": {
"ajv": "^8.8.2"
}
},
"node_modules/webpack/node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
},
"node_modules/webpack/node_modules/schema-utils": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz",
"integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==",
"dependencies": {
"@types/json-schema": "^7.0.9",
"ajv": "^8.9.0",
"ajv-formats": "^2.1.1",
"ajv-keywords": "^5.1.0"
},
"engines": {
"node": ">= 10.13.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
}
},
"node_modules/webpack/node_modules/webpack-sources": {
"version": "3.2.3",
"license": "MIT",

View file

@ -26,7 +26,7 @@
},
"dependencies": {
"@fortawesome/fontawesome-free": "^6.7.2",
"acorn": "^8.12.0",
"acorn": "^8.14.1",
"acorn-import-assertions": "^1.9.0",
"admin-lte": "^2.4.18",
"ajv": "^6.12.6",
@ -35,7 +35,7 @@
"bootstrap-colorpicker": "^2.5.3",
"bootstrap-datepicker": "^1.10.0",
"bootstrap-less": "^3.3.8",
"bootstrap-table": "1.24.0",
"bootstrap-table": "1.24.1",
"canvas-confetti": "^1.9.3",
"chart.js": "^2.9.4",
"clipboard": "^2.0.11",
@ -57,6 +57,6 @@
"signature_pad": "^4.2.0",
"tableexport.jquery.plugin": "1.30.0",
"tether": "^1.4.0",
"webpack": "^5.97.1"
"webpack": "^5.98.0"
}
}

View file

@ -1418,4 +1418,12 @@ input[type="radio"]:checked::before {
.bootstrap-table .fixed-table-container .table tbody tr .card-view {
display: table-row !important;
}
td.text-right.text-padding-number-cell {
padding-right: 30px !important;
white-space: nowrap;
}
th.text-right.text-padding-number-footer-cell {
padding-right: 20px !important;
white-space: nowrap;
}

View file

@ -1049,4 +1049,12 @@ input[type="radio"]:checked::before {
.bootstrap-table .fixed-table-container .table tbody tr .card-view {
display: table-row !important;
}
td.text-right.text-padding-number-cell {
padding-right: 30px !important;
white-space: nowrap;
}
th.text-right.text-padding-number-footer-cell {
padding-right: 20px !important;
white-space: nowrap;
}

View file

@ -21008,7 +21008,7 @@ hr {
@charset "UTF-8";
/**
* @author zhixin wen <wenzhixin2010@gmail.com>
* version: 1.24.0
* version: 1.24.1
* https://github.com/wenzhixin/bootstrap-table/
*/
/* stylelint-disable annotation-no-unknown, max-line-length */
@ -22753,6 +22753,14 @@ input[type="radio"]:checked::before {
.bootstrap-table .fixed-table-container .table tbody tr .card-view {
display: table-row !important;
}
td.text-right.text-padding-number-cell {
padding-right: 30px !important;
white-space: nowrap;
}
th.text-right.text-padding-number-footer-cell {
padding-right: 20px !important;
white-space: nowrap;
}
.select2-container {
@ -24288,4 +24296,12 @@ input[type="radio"]:checked::before {
.bootstrap-table .fixed-table-container .table tbody tr .card-view {
display: table-row !important;
}
td.text-right.text-padding-number-cell {
padding-right: 30px !important;
white-space: nowrap;
}
th.text-right.text-padding-number-footer-cell {
padding-right: 20px !important;
white-space: nowrap;
}

View file

@ -1,7 +1,7 @@
@charset "UTF-8";
/**
* @author zhixin wen <wenzhixin2010@gmail.com>
* version: 1.24.0
* version: 1.24.1
* https://github.com/wenzhixin/bootstrap-table/
*/
/* stylelint-disable annotation-no-unknown, max-line-length */

File diff suppressed because it is too large Load diff

1712
public/js/dist/all.js vendored

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/**
* bootstrap-table - An extended table to integration with some of the most widely used CSS frameworks. (Supports Bootstrap, Semantic UI, Bulma, Material Design, Foundation)
*
* @version v1.24.0
* @version v1.24.1
* @homepage https://bootstrap-table.com
* @author wenzhixin <wenzhixin2010@gmail.com> (http://wenzhixin.net.cn/)
* @license MIT

File diff suppressed because one or more lines are too long

View file

@ -6911,6 +6911,12 @@
}
return bootstrapVersion;
},
/**
* Returns the prefix for the icons based on the theme.
*
* @param {string} theme - The theme name (bootstrap3, bootstrap4, bootstrap5, bootstrap-table, bulma, foundation, materialize, semantic).
* @returns {string} The icons prefix.
*/
getIconsPrefix: function getIconsPrefix(theme) {
return {
bootstrap3: 'glyphicon',
@ -6923,75 +6929,28 @@
semantic: 'fa'
}[theme] || 'fa';
},
getIcons: function getIcons(prefix) {
return {
glyphicon: {
clearSearch: 'glyphicon-trash',
columns: 'glyphicon-th icon-th',
detailClose: 'glyphicon-minus icon-minus',
detailOpen: 'glyphicon-plus icon-plus',
fullscreen: 'glyphicon-fullscreen',
paginationSwitchDown: 'glyphicon-collapse-down icon-chevron-down',
paginationSwitchUp: 'glyphicon-collapse-up icon-chevron-up',
refresh: 'glyphicon-refresh icon-refresh',
search: 'glyphicon-search',
toggleOff: 'glyphicon-list-alt icon-list-alt',
toggleOn: 'glyphicon-list-alt icon-list-alt'
},
fa: {
clearSearch: 'fa-trash',
columns: 'fa-th-list',
detailClose: 'fa-minus',
detailOpen: 'fa-plus',
fullscreen: 'fa-arrows-alt',
paginationSwitchDown: 'fa-caret-square-down',
paginationSwitchUp: 'fa-caret-square-up',
refresh: 'fa-sync',
search: 'fa-search',
toggleOff: 'fa-toggle-off',
toggleOn: 'fa-toggle-on'
},
bi: {
clearSearch: 'bi-trash',
columns: 'bi-list-ul',
detailClose: 'bi-dash',
detailOpen: 'bi-plus',
fullscreen: 'bi-arrows-move',
paginationSwitchDown: 'bi-caret-down-square',
paginationSwitchUp: 'bi-caret-up-square',
refresh: 'bi-arrow-clockwise',
search: 'bi-search',
toggleOff: 'bi-toggle-off',
toggleOn: 'bi-toggle-on'
},
icon: {
clearSearch: 'icon-trash-2',
columns: 'icon-list',
detailClose: 'icon-minus',
detailOpen: 'icon-plus',
fullscreen: 'icon-maximize',
paginationSwitchDown: 'icon-arrow-up-circle',
paginationSwitchUp: 'icon-arrow-down-circle',
refresh: 'icon-refresh-cw',
search: 'icon-search',
toggleOff: 'icon-toggle-right',
toggleOn: 'icon-toggle-right'
},
'material-icons': {
clearSearch: 'delete',
columns: 'view_list',
detailClose: 'remove',
detailOpen: 'add',
fullscreen: 'fullscreen',
paginationSwitchDown: 'grid_on',
paginationSwitchUp: 'grid_off',
refresh: 'refresh',
search: 'search',
sort: 'sort',
toggleOff: 'tablet',
toggleOn: 'tablet_android'
}
}[prefix] || {};
/**
* Gets the icons for a given prefix.
*
* @param {Object.<string, Object>} icons - The icons object.
* @param {string} prefix - The prefix. For example, 'fa', 'bi', etc.
* @return {Object} The icons object for the given prefix.
*/
getIcons: function getIcons(icons, prefix) {
return icons[prefix] || {};
},
/**
* Assigns new icons to icons object.
*
* @param {Object.<string, Object>} icons - The icons object.
* @param {string} icon - The icon name. For example, 'search', 'refresh', etc.
* @param {Object.<string, string>} values - The values object.
*/
assignIcons: function assignIcons(icons, icon, values) {
for (var _i = 0, _Object$keys = Object.keys(icons); _i < _Object$keys.length; _i++) {
var key = _Object$keys[_i];
icons[key][icon] = values[key];
}
},
getSearchInput: function getSearchInput(that) {
if (typeof that.options.searchSelector === 'string') {
@ -7145,15 +7104,15 @@
flag[i][j] = false;
}
}
for (var _i = 0; _i < columns.length; _i++) {
var _iterator3 = _createForOfIteratorHelper(columns[_i]),
for (var _i2 = 0; _i2 < columns.length; _i2++) {
var _iterator3 = _createForOfIteratorHelper(columns[_i2]),
_step3;
try {
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
var r = _step3.value;
var rowspan = +r.rowspan || 1;
var colspan = +r.colspan || 1;
var index = flag[_i].indexOf(false);
var index = flag[_i2].indexOf(false);
r.colspanIndex = index;
if (colspan === 1) {
r.fieldIndex = index;
@ -7166,7 +7125,7 @@
}
for (var _j = 0; _j < rowspan; _j++) {
for (var k = 0; k < colspan; k++) {
flag[_i + _j][index + k] = true;
flag[_i2 + _j][index + k] = true;
}
}
}
@ -7322,8 +7281,8 @@
if (compareLength && aKeys.length !== bKeys.length) {
return false;
}
for (var _i2 = 0, _aKeys = aKeys; _i2 < _aKeys.length; _i2++) {
var key = _aKeys[_i2];
for (var _i3 = 0, _aKeys = aKeys; _i3 < _aKeys.length; _i3++) {
var key = _aKeys[_i3];
if (bKeys.includes(key) && objectA[key] !== objectB[key]) {
return false;
}
@ -7364,8 +7323,8 @@
return text.toString().replace(/(<([^>]+)>)/ig, '').replace(/&[#A-Za-z0-9]+;/gi, '').trim();
},
getRealDataAttr: function getRealDataAttr(dataAttr) {
for (var _i3 = 0, _Object$entries = Object.entries(dataAttr); _i3 < _Object$entries.length; _i3++) {
var _Object$entries$_i = _slicedToArray(_Object$entries[_i3], 2),
for (var _i4 = 0, _Object$entries = Object.entries(dataAttr); _i4 < _Object$entries.length; _i4++) {
var _Object$entries$_i = _slicedToArray(_Object$entries[_i4], 2),
attr = _Object$entries$_i[0],
value = _Object$entries$_i[1];
var auxAttr = attr.split(/(?=[A-Z])/).join('-').toLowerCase();
@ -7534,8 +7493,8 @@
try {
for (_iterator11.s(); !(_step11 = _iterator11.n()).done;) {
var row = _step11.value;
for (var _i4 = 0, _Object$keys = Object.keys(row); _i4 < _Object$keys.length; _i4++) {
var key = _Object$keys[_i4];
for (var _i5 = 0, _Object$keys2 = Object.keys(row); _i5 < _Object$keys2.length; _i5++) {
var key = _Object$keys2[_i5];
if (key.startsWith('_') && (key.endsWith('_rowspan') || key.endsWith('_colspan'))) {
return true;
}
@ -7679,8 +7638,8 @@
_iterator13.f();
}
} else if (_typeof(style) === 'object') {
for (var _i5 = 0, _Object$entries2 = Object.entries(style); _i5 < _Object$entries2.length; _i5++) {
var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i5], 2),
for (var _i6 = 0, _Object$entries2 = Object.entries(style); _i6 < _Object$entries2.length; _i6++) {
var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i6], 2),
k = _Object$entries2$_i[0],
v = _Object$entries2$_i[1];
dom.style.setProperty(k, v);
@ -7697,8 +7656,8 @@
if (el.tagName === 'A') {
el.href = 'javascript:';
}
for (var _i6 = 0, _Object$entries3 = Object.entries(_attrs); _i6 < _Object$entries3.length; _i6++) {
var _Object$entries3$_i = _slicedToArray(_Object$entries3[_i6], 2),
for (var _i7 = 0, _Object$entries3 = Object.entries(_attrs); _i7 < _Object$entries3.length; _i7++) {
var _Object$entries3$_i = _slicedToArray(_Object$entries3[_i7], 2),
k = _Object$entries3$_i[0],
v = _Object$entries3$_i[1];
if (v === undefined) {
@ -7756,8 +7715,8 @@
baseUrl = _hashArray$0$split2[0],
search = _hashArray$0$split2[1];
var urlParams = new URLSearchParams(search);
for (var _i7 = 0, _Object$entries4 = Object.entries(query); _i7 < _Object$entries4.length; _i7++) {
var _Object$entries4$_i = _slicedToArray(_Object$entries4[_i7], 2),
for (var _i8 = 0, _Object$entries4 = Object.entries(query); _i8 < _Object$entries4.length; _i8++) {
var _Object$entries4$_i = _slicedToArray(_Object$entries4[_i8], 2),
key = _Object$entries4$_i[0],
value = _Object$entries4$_i[1];
urlParams.set(key, value);
@ -7766,7 +7725,7 @@
}
};
var VERSION = '1.24.0';
var VERSION = '1.24.1';
var bootstrapVersion = Utils.getBootstrapVersion();
var CONSTANTS = {
3: {
@ -7870,6 +7829,74 @@
}
}
}[bootstrapVersion];
var ICONS = {
glyphicon: {
clearSearch: 'glyphicon-trash',
columns: 'glyphicon-th icon-th',
detailClose: 'glyphicon-minus icon-minus',
detailOpen: 'glyphicon-plus icon-plus',
fullscreen: 'glyphicon-fullscreen',
paginationSwitchDown: 'glyphicon-collapse-down icon-chevron-down',
paginationSwitchUp: 'glyphicon-collapse-up icon-chevron-up',
refresh: 'glyphicon-refresh icon-refresh',
search: 'glyphicon-search',
toggleOff: 'glyphicon-list-alt icon-list-alt',
toggleOn: 'glyphicon-list-alt icon-list-alt'
},
fa: {
clearSearch: 'fa-trash',
columns: 'fa-th-list',
detailClose: 'fa-minus',
detailOpen: 'fa-plus',
fullscreen: 'fa-arrows-alt',
paginationSwitchDown: 'fa-caret-square-down',
paginationSwitchUp: 'fa-caret-square-up',
refresh: 'fa-sync',
search: 'fa-search',
toggleOff: 'fa-toggle-off',
toggleOn: 'fa-toggle-on'
},
bi: {
clearSearch: 'bi-trash',
columns: 'bi-list-ul',
detailClose: 'bi-dash',
detailOpen: 'bi-plus',
fullscreen: 'bi-arrows-move',
paginationSwitchDown: 'bi-caret-down-square',
paginationSwitchUp: 'bi-caret-up-square',
refresh: 'bi-arrow-clockwise',
search: 'bi-search',
toggleOff: 'bi-toggle-off',
toggleOn: 'bi-toggle-on'
},
icon: {
clearSearch: 'icon-trash-2',
columns: 'icon-list',
detailClose: 'icon-minus',
detailOpen: 'icon-plus',
fullscreen: 'icon-maximize',
paginationSwitchDown: 'icon-arrow-up-circle',
paginationSwitchUp: 'icon-arrow-down-circle',
refresh: 'icon-refresh-cw',
search: 'icon-search',
toggleOff: 'icon-toggle-right',
toggleOn: 'icon-toggle-right'
},
'material-icons': {
clearSearch: 'delete',
columns: 'view_list',
detailClose: 'remove',
detailOpen: 'add',
fullscreen: 'fullscreen',
paginationSwitchDown: 'grid_on',
paginationSwitchUp: 'grid_off',
refresh: 'refresh',
search: 'search',
sort: 'sort',
toggleOff: 'tablet',
toggleOn: 'tablet_android'
}
};
var DEFAULTS = {
ajax: undefined,
ajaxOptions: {},
@ -8282,6 +8309,7 @@
CONSTANTS: CONSTANTS,
DEFAULTS: DEFAULTS,
EVENTS: EVENTS,
ICONS: ICONS,
LOCALES: {
en: EN,
'en-US': EN
@ -8462,7 +8490,7 @@
opts.icons = Utils.calculateObjectValue(null, opts.icons);
}
opts.iconsPrefix = opts.iconsPrefix || $.fn.bootstrapTable.defaults.iconsPrefix || iconsPrefix;
opts.icons = Object.assign(Utils.getIcons(opts.iconsPrefix), $.fn.bootstrapTable.defaults.icons, opts.icons);
opts.icons = Object.assign(Utils.getIcons(Constants.ICONS, opts.iconsPrefix), $.fn.bootstrapTable.defaults.icons, opts.icons);
// init buttons class
var buttonsPrefix = opts.buttonsPrefix ? "".concat(opts.buttonsPrefix, "-") : '';
@ -9461,7 +9489,10 @@
html.push("<div class=\"".concat(this.constants.classes.pull, "-").concat(opts.paginationDetailHAlign, " pagination-detail\">"));
}
if (this.paginationParts.includes('pageInfo') || this.paginationParts.includes('pageInfoShort')) {
var totalRows = this.options.totalRows + (this.options.sidePagination === 'client' && this.options.paginationLoadMore && !this._paginationLoaded && this.totalPages > 1 ? ' +' : '');
var totalRows = this.options.totalRows;
if (this.options.sidePagination === 'client' && this.options.paginationLoadMore && !this._paginationLoaded && this.totalPages > 1) {
totalRows += ' +';
}
var paginationInfo = this.paginationParts.includes('pageInfoShort') ? opts.formatDetailPagination(totalRows) : opts.formatShowingRows(this.pageFrom, this.pageTo, totalRows, opts.totalNotFiltered);
html.push("<span class=\"pagination-info\">\n ".concat(paginationInfo, "\n </span>"));
}
@ -11251,7 +11282,7 @@
}, {
key: "filterBy",
value: function filterBy(columns, options) {
this.filterOptions = Utils.isEmptyObject(options) ? this.options.filterOptions : Utils.extend(this.options.filterOptions, options);
this.filterOptions = Utils.isEmptyObject(options) ? this.options.filterOptions : Utils.extend({}, this.options.filterOptions, options);
this.filterColumns = Utils.isEmptyObject(columns) ? {} : columns;
this.options.pageNumber = 1;
this.initSearch();
@ -11470,6 +11501,7 @@
$.fn.bootstrapTable.Constructor = BootstrapTable;
$.fn.bootstrapTable.theme = Constants.THEME;
$.fn.bootstrapTable.VERSION = Constants.VERSION;
$.fn.bootstrapTable.icons = Constants.ICONS;
$.fn.bootstrapTable.defaults = BootstrapTable.DEFAULTS;
$.fn.bootstrapTable.columnDefaults = BootstrapTable.COLUMN_DEFAULTS;
$.fn.bootstrapTable.events = BootstrapTable.EVENTS;
@ -17521,13 +17553,12 @@
forceExport: false,
forceHide: false
});
Object.assign($.fn.bootstrapTable.defaults.icons, {
export: {
bootstrap3: 'glyphicon-export icon-share',
bootstrap5: 'bi-download',
materialize: 'file_download',
'bootstrap-table': 'icon-download'
}[$.fn.bootstrapTable.theme] || 'fa-download'
Utils.assignIcons($.fn.bootstrapTable.icons, 'export', {
glyphicon: 'glyphicon-export icon-share',
fa: 'fa-download',
bi: 'bi-download',
icon: 'icon-download',
'material-icons': 'file_download'
});
Object.assign($.fn.bootstrapTable.locales, {
formatExport: function formatExport() {
@ -22124,11 +22155,12 @@
}, {
key: "configureStorage",
value: function configureStorage() {
var _this2 = this;
this._storage = {};
switch (this.options.cookieStorage) {
case 'cookieStorage':
this._storage.setItem = function (cookieName, cookieValue) {
document.cookie = [cookieName, '=', encodeURIComponent(cookieValue), "; expires=".concat(UtilsCookie.calculateExpiration(this.options.cookieExpire)), this.options.cookiePath ? "; path=".concat(this.options.cookiePath) : '', this.options.cookieDomain ? "; domain=".concat(this.options.cookieDomain) : '', this.options.cookieSecure ? '; secure' : '', ";SameSite=".concat(this.options.cookieSameSite)].join('');
document.cookie = [cookieName, '=', encodeURIComponent(cookieValue), "; expires=".concat(UtilsCookie.calculateExpiration(_this2.options.cookieExpire)), _this2.options.cookiePath ? "; path=".concat(_this2.options.cookiePath) : '', _this2.options.cookieDomain ? "; domain=".concat(_this2.options.cookieDomain) : '', _this2.options.cookieSecure ? '; secure' : '', ";SameSite=".concat(_this2.options.cookieSameSite)].join('');
};
this._storage.getItem = function (cookieName) {
var value = "; ".concat(document.cookie);
@ -22136,7 +22168,7 @@
return parts.length === 2 ? decodeURIComponent(parts.pop().split(';').shift()) : null;
};
this._storage.removeItem = function (cookieName) {
document.cookie = [encodeURIComponent(cookieName), '=', '; expires=Thu, 01 Jan 1970 00:00:00 GMT', this.options.cookiePath ? "; path=".concat(this.options.cookiePath) : '', this.options.cookieDomain ? "; domain=".concat(this.options.cookieDomain) : '', ";SameSite=".concat(this.options.cookieSameSite)].join('');
document.cookie = [encodeURIComponent(cookieName), '=', '; expires=Thu, 01 Jan 1970 00:00:00 GMT', _this2.options.cookiePath ? "; path=".concat(_this2.options.cookiePath) : '', _this2.options.cookieDomain ? "; domain=".concat(_this2.options.cookieDomain) : '', ";SameSite=".concat(_this2.options.cookieSameSite)].join('');
};
break;
case 'localStorage':
@ -22166,13 +22198,13 @@
throw new Error('The following options must be set while using the customStorage: cookieCustomStorageSet, cookieCustomStorageGet and cookieCustomStorageDelete');
}
this._storage.setItem = function (cookieName, cookieValue) {
Utils.calculateObjectValue(this.options, this.options.cookieCustomStorageSet, [cookieName, cookieValue], '');
Utils.calculateObjectValue(_this2.options, _this2.options.cookieCustomStorageSet, [cookieName, cookieValue], '');
};
this._storage.getItem = function (cookieName) {
return Utils.calculateObjectValue(this.options, this.options.cookieCustomStorageGet, [cookieName], '');
return Utils.calculateObjectValue(_this2.options, _this2.options.cookieCustomStorageGet, [cookieName], '');
};
this._storage.removeItem = function (cookieName) {
Utils.calculateObjectValue(this.options, this.options.cookieCustomStorageDelete, [cookieName], '');
Utils.calculateObjectValue(_this2.options, _this2.options.cookieCustomStorageDelete, [cookieName], '');
};
break;
default:
@ -35674,27 +35706,18 @@ if(xr(e,"index.xml"))throw new Error("Unsupported NUMBERS 09 file");throw new Er
var Utils = $.fn.bootstrapTable.utils;
var theme = {
bootstrap3: {
icons: {
advancedSearchIcon: 'glyphicon-chevron-down'
},
classes: {},
html: {
modal: "\n <div id=\"avdSearchModal_%s\" class=\"modal fade\" tabindex=\"-1\" role=\"dialog\" aria-hidden=\"true\">\n <div class=\"modal-dialog modal-xs\">\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n <button class=\"close toolbar-modal-close\" data-dismiss=\"modal\" aria-label=\"Close\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n <h4 class=\"modal-title toolbar-modal-title\"></h4>\n </div>\n <div class=\"modal-body toolbar-modal-body\"></div>\n <div class=\"modal-footer toolbar-modal-footer\">\n <button class=\"btn btn-%s toolbar-modal-close\"></button>\n </div>\n </div>\n </div>\n </div>\n "
}
},
bootstrap4: {
icons: {
advancedSearchIcon: 'fa-chevron-down'
},
classes: {},
html: {
modal: "\n <div id=\"avdSearchModal_%s\" class=\"modal fade\" tabindex=\"-1\" role=\"dialog\" aria-hidden=\"true\">\n <div class=\"modal-dialog modal-xs\">\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n <h4 class=\"modal-title toolbar-modal-title\"></h4>\n <button class=\"close toolbar-modal-close\" data-dismiss=\"modal\" aria-label=\"Close\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n </div>\n <div class=\"modal-body toolbar-modal-body\"></div>\n <div class=\"modal-footer toolbar-modal-footer\">\n <button class=\"btn btn-%s toolbar-modal-close\"></button>\n </div>\n </div>\n </div>\n </div>\n "
}
},
bootstrap5: {
icons: {
advancedSearchIcon: 'bi-chevron-down'
},
classes: {
formGroup: 'mb-3'
},
@ -35703,36 +35726,24 @@ if(xr(e,"index.xml"))throw new Error("Unsupported NUMBERS 09 file");throw new Er
}
},
bulma: {
icons: {
advancedSearchIcon: 'fa-chevron-down'
},
classes: {},
html: {
modal: "\n <div class=\"modal\" id=\"avdSearchModal_%s\">\n <div class=\"modal-background\"></div>\n <div class=\"modal-card\">\n <header class=\"modal-card-head\">\n <p class=\"modal-card-title toolbar-modal-title\"></p>\n <button class=\"delete toolbar-modal-close\"></button>\n </header>\n <section class=\"modal-card-body toolbar-modal-body\"></section>\n <footer class=\"modal-card-foot toolbar-modal-footer\">\n <button class=\"button button-%s toolbar-modal-close\"></button>\n </footer>\n </div>\n </div>\n "
}
},
foundation: {
icons: {
advancedSearchIcon: 'fa-chevron-down'
},
classes: {},
html: {
modal: "\n <div class=\"reveal\" id=\"avdSearchModal_%s\" data-reveal>\n <h1 class=\"toolbar-modal-title\"></h1>\n <div class=\"toolbar-modal-body\"></div>\n <button class=\"close-button toolbar-modal-close\" data-close aria-label=\"Close modal\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n <div class=\"toolbar-modal-footer\">\n <button class=\"button button-%s toolbar-modal-close\"></button>\n </div>\n </div>\n "
}
},
materialize: {
icons: {
advancedSearchIcon: 'expand_more'
},
classes: {},
html: {
modal: "\n <div id=\"avdSearchModal_%s\" class=\"modal\">\n <div class=\"modal-content\">\n <h4 class=\"toolbar-modal-title\"></h4>\n <div class=\"toolbar-modal-body\"></div>\n </div>\n <div class=\"modal-footer toolbar-modal-footer\">\n <a href=\"javascript:void(0)\" class=\"modal-close waves-effect waves-green btn-flat btn-%s toolbar-modal-close\"></a>\n </div>\n </div>\n "
}
},
semantic: {
icons: {
advancedSearchIcon: 'fa-chevron-down'
},
classes: {},
html: {
modal: "\n <div class=\"ui modal\" id=\"avdSearchModal_%s\">\n <i class=\"close icon toolbar-modal-close\"></i>\n <div class=\"header toolbar-modal-title\"\"></div>\n <div class=\"image content ui form toolbar-modal-body\"></div>\n <div class=\"actions toolbar-modal-footer\">\n <div class=\"ui black deny button button-%s toolbar-modal-close\"></div>\n </div>\n </div>\n "
@ -35749,8 +35760,11 @@ if(xr(e,"index.xml"))throw new Error("Unsupported NUMBERS 09 file");throw new Er
return false;
}
});
Object.assign($.fn.bootstrapTable.defaults.icons, {
advancedSearchIcon: theme.icons.advancedSearchIcon
Utils.assignIcons($.fn.bootstrapTable.icons, 'advancedSearchIcon', {
glyphicon: 'glyphicon-chevron-down',
fa: 'fa-chevron-down',
bi: 'bi-chevron-down',
'material-icons': 'expand_more'
});
Object.assign($.fn.bootstrapTable.events, {
'column-advanced-search.bs.table': 'onColumnAdvancedSearch'

View file

@ -1,9 +1,9 @@
{
"/js/build/app.js": "/js/build/app.js?id=65d7af7b9fa7fd0e05737526a0d1d282",
"/js/build/app.js": "/js/build/app.js?id=607de09b70b83ef82a427e4b36341682",
"/css/dist/skins/skin-black-dark.css": "/css/dist/skins/skin-black-dark.css?id=06c13e817cc022028b3f4a33c0ca303a",
"/css/dist/skins/_all-skins.css": "/css/dist/skins/_all-skins.css?id=79aa889a1a6691013be6c342ca7391cd",
"/css/build/overrides.css": "/css/build/overrides.css?id=6528155ed5ed8fddf4047de7f0d0298d",
"/css/build/app.css": "/css/build/app.css?id=3422f2ca2056b952c3c361adf00c10b8",
"/css/build/overrides.css": "/css/build/overrides.css?id=f188c07f91348503bc38f4b6683993aa",
"/css/build/app.css": "/css/build/app.css?id=7f6827b6d2149b8eab327d00e2dd66f0",
"/css/build/AdminLTE.css": "/css/build/AdminLTE.css?id=4ea0068716c1bb2434d87a16d51b98c9",
"/css/dist/skins/skin-yellow.css": "/css/dist/skins/skin-yellow.css?id=7b315b9612b8fde8f9c5b0ddb6bba690",
"/css/dist/skins/skin-yellow-dark.css": "/css/dist/skins/skin-yellow-dark.css?id=ea22079836a432d7f46a5d390c445e13",
@ -19,7 +19,7 @@
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=a82b065847bf3cd5d713c04ee8dc86c6",
"/css/dist/skins/skin-blue-dark.css": "/css/dist/skins/skin-blue-dark.css?id=6ea836d8126de101081c49abbdb89417",
"/css/dist/skins/skin-black.css": "/css/dist/skins/skin-black.css?id=76482123f6c70e866d6b971ba91de7bb",
"/css/dist/all.css": "/css/dist/all.css?id=18ebb9c284b49dcf6c8e4fdb923ad923",
"/css/dist/all.css": "/css/dist/all.css?id=e6bb343692dc7255405be1793f149e0a",
"/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",
"/js/select2/i18n/af.js": "/js/select2/i18n/af.js?id=4f6fcd73488ce79fae1b7a90aceaecde",
@ -90,8 +90,8 @@
"/css/webfonts/fa-solid-900.woff2": "/css/webfonts/fa-solid-900.woff2?id=109ad919b74a62a8a223361da1651bbc",
"/css/webfonts/fa-v4compatibility.ttf": "/css/webfonts/fa-v4compatibility.ttf?id=53c2e50ef821f7b8dd514611d5e0772c",
"/css/webfonts/fa-v4compatibility.woff2": "/css/webfonts/fa-v4compatibility.woff2?id=331c85bd61ffa93af09273d1bc2add5a",
"/js/dist/bootstrap-table-locale-all.min.js": "/js/dist/bootstrap-table-locale-all.min.js?id=02dfc50d5b951dc6d260bd508968d319",
"/js/dist/bootstrap-table-en-US.min.js": "/js/dist/bootstrap-table-en-US.min.js?id=1c350eabf064c309f67d6779e5cc4afa",
"/js/dist/bootstrap-table-locale-all.min.js": "/js/dist/bootstrap-table-locale-all.min.js?id=5e93ef0a1889bed3f92a705dc1e92c9b",
"/js/dist/bootstrap-table-en-US.min.js": "/js/dist/bootstrap-table-en-US.min.js?id=c0f21fb7e62d6f0a0153f1cdbf26782a",
"/css/dist/skins/_all-skins.min.css": "/css/dist/skins/_all-skins.min.css?id=79aa889a1a6691013be6c342ca7391cd",
"/css/dist/skins/skin-black-dark.min.css": "/css/dist/skins/skin-black-dark.min.css?id=06c13e817cc022028b3f4a33c0ca303a",
"/css/dist/skins/skin-black.min.css": "/css/dist/skins/skin-black.min.css?id=76482123f6c70e866d6b971ba91de7bb",
@ -108,8 +108,8 @@
"/css/dist/skins/skin-red.min.css": "/css/dist/skins/skin-red.min.css?id=44bf834f2110504a793dadec132a5898",
"/css/dist/skins/skin-yellow-dark.min.css": "/css/dist/skins/skin-yellow-dark.min.css?id=ea22079836a432d7f46a5d390c445e13",
"/css/dist/skins/skin-yellow.min.css": "/css/dist/skins/skin-yellow.min.css?id=7b315b9612b8fde8f9c5b0ddb6bba690",
"/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=ceded08e0cc745a83c13647035b03406",
"/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=54d676a6ea8677dd48f6c4b3041292cf",
"/js/build/vendor.js": "/js/build/vendor.js?id=89dffa552c6e3abe3a2aac6c9c7b466b",
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=61285c8ac5ea7b46002ea8c451c94e60",
"/js/dist/all.js": "/js/dist/all.js?id=21e041dec60e0785db6d64961b13a9b0"
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=757648759dcd365f5708e95b985971ff",
"/js/dist/all.js": "/js/dist/all.js?id=cae553daff19b328b3ba51a62f891442"
}

View file

@ -1163,4 +1163,15 @@ input[type="radio"]:checked::before {
/** this is needed to override ekko-lightboxes card view styles **/
.bootstrap-table .fixed-table-container .table tbody tr .card-view {
display: table-row !important;
}
}
td.text-right.text-padding-number-cell {
padding-right: 30px !important;
white-space: nowrap;
}
th.text-right.text-padding-number-footer-cell {
padding-right: 20px !important;
white-space: nowrap;
}

View file

@ -58,10 +58,8 @@ return [
'display_eol' => 'Display EOL in table view',
'display_qr' => 'Display 2D barcode',
'display_alt_barcode' => 'Display 1D barcode',
'email_logo' => 'Email Logo',
'barcode_type' => '2D Barcode Type',
'alt_barcode_type' => '1D barcode type',
'email_logo_size' => 'Square logos in email look best. ',
'enabled' => 'Enabled',
'eula_settings' => 'EULA Settings',
'eula_markdown' => 'This EULA allows <a href="https://help.github.com/articles/github-flavored-markdown/">Github flavored markdown</a>.',
@ -77,7 +75,6 @@ return [
'google_workspaces' => 'Google Workspaces',
'header_color' => 'Header Color',
'info' => 'These settings let you customize certain aspects of your installation.',
'label_logo' => 'Label Logo',
'label_logo_size' => 'Square logos look best - will be displayed in the top right of each asset label. ',
'laravel' => 'Laravel Version',
'ldap' => 'LDAP',
@ -389,7 +386,7 @@ return [
'test_mail' => 'Test Mail',
'profile_edit' => 'Edit Profile',
'profile_edit_help' => 'Allow users to edit their own profiles.',
'default_avatar' => 'Upload custom default avatar',
'default_avatar' => 'Custom Default Avatar',
'default_avatar_help' => 'This image will be displayed as a profile if a user does not have a profile photo.',
'restore_default_avatar' => 'Restore <a href=":default_avatar" data-toggle="lightbox" data-type="image">original system default avatar</a>',
'restore_default_avatar_help' => '',
@ -398,6 +395,17 @@ return [
'no_groups' => 'No groups have been created yet. Visit <code>Admin Settings > Permission Groups</code> to add one.',
'text' => 'Text',
'logo_labels' => [
'acceptance_pdf_logo' => 'PDF Logo',
'email_logo' => 'Email Logo',
'label_logo' => 'Label Logo',
'logo' => 'Site Logo',
'favicon' => 'Favicon',
],
'logo_help' => [
'email_logo_size' => 'Square logos in email look best. ',
],
'logo_option_types' => [
'text' => 'Text',

View file

@ -15,6 +15,6 @@ return array(
'failed' => 'These credentials do not match our records.',
'password' => 'The provided password is incorrect.',
'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
'throttle' => 'Too many login attempts. Please try again in :minutes minute(s).',
);

View file

@ -6,8 +6,6 @@ return array(
'account_not_found' => 'The username or password is incorrect.',
'account_not_activated' => 'This user account is not activated.',
'account_suspended' => 'This user account is suspended.',
'account_banned' => 'This user account is banned.',
'throttle' => 'Too many failed login attempts. Please try again in :minutes minutes.',
'two_factor' => array(
'already_enrolled' => 'Your device is already enrolled.',

View file

@ -34,6 +34,7 @@
data-show-refresh="true"
data-show-footer="true"
data-sort-order="asc"
data-footer-style="footerStyle"
id="accessoriesTable"
class="table table-striped snipe-table"
data-url="{{route('api.accessories.index') }}"

View file

@ -0,0 +1,62 @@
@use('App\Models\Location', 'Location')
@use('Illuminate\Support\Arr', 'Arr')
@props([
'label',
'name',
'selected',
'required' => false,
'multiple' => false,
'helpText' => null,
'hideNewButton' => false,
])
<div
@class([
'form-group',
'has-error' => $errors->has($name),
])
>
<label for="{{ $name }}" class="col-md-3 control-label">{{ $label }}</label>
<div class="col-md-7">
<select
class="js-data-ajax"
data-endpoint="locations"
data-placeholder="{{ trans('general.select_location') }}"
name="{{ $name }}"
style="width: 100%"
id="{{ $name }}_location_select"
aria-label="{{ $name }}"
@required($required)
@if ($multiple)
multiple
@endif
>
@if ($selected)
@foreach(Arr::wrap($selected) as $id)
<option value="{{ $id }}" selected="selected" role="option" aria-selected="true" role="option">
{{ optional(Location::find($id))->name }}
</option>
@endforeach
@endif
</select>
</div>
<div class="col-md-1 col-sm-1 text-left">
@unless($hideNewButton)
@can('create', Location::class)
<a href='{{ route('modal.show', 'location') }}' data-toggle="modal" data-target="#createModal" data-select='{{ $name }}_location_select' class="btn btn-sm btn-primary">{{ trans('button.new') }}</a>
@endcan
@endunless
</div>
{!! $errors->first($name, '<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>') !!}
@if ($helpText)
<div class="col-md-7 col-sm-11 col-md-offset-3">
<p class="help-block">{{ $helpText }}</p>
</div>
@endif
</div>

View file

@ -0,0 +1,25 @@
@props([
// <options> can either be provided as key => value pairs
// or passed in via the default $slot
'options',
'selected' => null,
'includeEmpty' => false,
'forLivewire' => false,
])
<select
{{ $attributes->class(['select2', 'livewire-select2' => $forLivewire]) }}
@if($forLivewire) data-livewire-component="{{ $this->getId() }}" @endif
>
@if($includeEmpty)
<option value=""></option>
@endif
{{-- map the simple key => value pairs when nothing is passed in via the slot --}}
@if($slot->isEmpty())
@foreach($options as $key => $value)
<option value="{{ $key }}" @selected($selected == $key)>{{ $value }}</option>
@endforeach
@else
{{ $slot }}
@endif
</select>

View file

@ -15,7 +15,14 @@
<div class="form-group {{ $errors->has('category_type') ? ' has-error' : '' }}">
<label for="category_type" class="col-md-3 control-label">{{ trans('general.type') }}</label>
<div class="col-md-7 required">
{{ Form::select('category_type', $category_types , old('category_type', $item->category_type), array('class'=>'select2', 'style'=>'min-width:350px', 'aria-label'=>'category_type', ($item->category_type!='') || ($item->itemCount() > 0) ? 'disabled' : '')) }}
<x-input.select
name="category_type"
:options="$category_types"
:selected="old('category_type', $item->category_type)"
:disabled="$item->category_type!='' || $item->itemCount() > 0"
style="min-width:350px"
aria-label="category_type"
/>
{!! $errors->first('category_type', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
<div class="col-md-7 col-md-offset-3">

View file

@ -25,6 +25,7 @@
data-id-table="componentsTable"
data-search="true"
data-side-pagination="server"
data-footer-style="footerStyle"
data-show-columns="true"
data-show-fullscreen="true"
data-show-export="true"

View file

@ -27,6 +27,7 @@
data-id-table="consumablesTable"
data-search="true"
data-side-pagination="server"
data-footer-style="footerStyle"
data-show-columns="true"
data-show-export="true"
data-show-fullscreen="true"

View file

@ -292,8 +292,10 @@
</div>
<div class="col-md-9">
<span class="js-copy">{{ $consumable->item_no }}</span>
<i class="fa-regular fa-clipboard js-copy-link" data-clipboard-target=".js-copy" aria-hidden="true" data-tooltip="true" data-placement="top" title="{{ trans('general.copy_to_clipboard') }}">
<span class="js-copy-item_no">{{ $consumable->item_no }}</span>
<i class="fa-regular fa-clipboard js-copy-link" data-clipboard-target=".js-copy-item_no"
aria-hidden="true" data-tooltip="true" data-placement="top"
title="{{ trans('general.copy_to_clipboard') }}">
<span class="sr-only">{{ trans('general.copy_to_clipboard') }}</span>
</i>
@ -308,8 +310,10 @@
</div>
<div class="col-md-9">
<span class="js-copy">{{ $consumable->model_number }}</span>
<i class="fa-regular fa-clipboard js-copy-link" data-clipboard-target=".js-copy" aria-hidden="true" data-tooltip="true" data-placement="top" title="{{ trans('general.copy_to_clipboard') }}">
<span class="js-copy-model_no">{{ $consumable->model_number }}</span>
<i class="fa-regular fa-clipboard js-copy-link" data-clipboard-target=".js-copy-model_no"
aria-hidden="true" data-tooltip="true" data-placement="top"
title="{{ trans('general.copy_to_clipboard') }}">
<span class="sr-only">{{ trans('general.copy_to_clipboard') }}</span>
</i>
@ -329,6 +333,22 @@
</div>
@endif
@if ($consumable->adminuser)
<!-- created at -->
<div class="row">
<div class="col-md-3">
{{ trans('general.created_by') }}
</div>
<div class="col-md-9">
@if ($consumable->adminuser->deleted_at == '')
<a href="{{ route('users.show', ['user' => $consumable->adminuser]) }}">{{ $consumable->adminuser->present()->fullName }}</a>
@else
<del>{{ $consumable->adminuser->present()->fullName }}</del>
@endif
</div>
</div>
@endif
@if ($consumable->created_at)
<!-- created at -->
<div class="row">
@ -353,24 +373,6 @@
</div>
@endif
@if ($consumable->admin)
<!-- created at -->
<div class="row">
<div class="col-md-3">
{{ trans('general.created_by') }}
</div>
<div class="col-md-9">
@if ($consumable->admin->deleted_at == '')
<a href="{{ route('users.show', ['user' => $consumable->admin]) }}">{{ $consumable->admin->present()->fullName }}</a>
@else
<del>{{ $consumable->admin->present()->fullName }}</del>
@endif
</div>
</div>
@endif
@if ($consumable->notes)
<!-- empty -->
<div class="row">

View file

@ -94,7 +94,14 @@
}
@endphp
<div class="col-md-8 required">
{{ Form::select("format",Helper::predefined_formats(), ($field_format == '') ? $field->format : $field_format, array('class'=>'format select2 form-control', 'aria-label'=>'format', 'style' => 'width:100%;')) }}
<x-input.select
name="format"
:options="Helper::predefined_formats()"
:selected="($field_format == '') ? $field->format : $field_format"
class="format form-control"
style="width:100%"
aria-label="format"
/>
{!! $errors->first('format', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
</div>

View file

@ -95,8 +95,12 @@
<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', 'style' => 'min-width:400px;']) }}
<x-input.select
name="field_id"
:options="$custom_fields_list"
style="min-width:400px"
aria-label="field_id"
/>
</div>
<div class="form-group" style="display: none;">

View file

@ -238,7 +238,7 @@
<tr>
<th data-field="icon" data-visible="true" style="width: 40px;" class="hidden-xs" data-formatter="iconFormatter"><span class="sr-only">{{ trans('admin/hardware/table.icon') }}</span></th>
<th class="col-sm-3" data-visible="true" data-field="created_at" data-formatter="dateDisplayFormatter">{{ trans('general.date') }}</th>
<th class="col-sm-2" data-visible="true" data-field="admin" data-formatter="usersLinkObjFormatter">{{ trans('general.admin') }}</th>
<th class="col-sm-2" data-visible="true" data-field="admin" data-formatter="usersLinkObjFormatter">{{ trans('general.created_by') }}</th>
<th class="col-sm-2" data-visible="true" data-field="action_type">{{ trans('general.action') }}</th>
<th class="col-sm-3" data-visible="true" data-field="item" data-formatter="polymorphicItemFormatter">{{ trans('general.item') }}</th>
<th class="col-sm-2" data-visible="true" data-field="target" data-formatter="polymorphicItemFormatter">{{ trans('general.target') }}</th>

View file

@ -171,7 +171,7 @@
</div>
</div>
{{ Form::close() }}
</form>
</div> <!--/.row-->
</div> <!-- /.tab-pane -->

View file

@ -125,7 +125,13 @@
{{ trans('admin/hardware/form.status') }}
</label>
<div class="col-md-7">
{{ Form::select('status_id', $statuslabel_list , old('status_id'), array('class'=>'select2', 'style'=>'width:100%', 'aria-label'=>'status_id')) }}
<x-input.select
name="status_id"
:options="$statuslabel_list"
:selected="old('status_id')"
style="width: 100%"
aria-label="status_id"
/>
<p class="help-block">{{ trans('general.status_compatibility') }}</p>
{!! $errors->first('status_id', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>

View file

@ -84,12 +84,37 @@
{{ trans('admin/hardware/form.status') }}
</label>
<div class="col-md-8 required">
{{ Form::select('status_id', $statusLabel_list, '', array('class'=>'select2', 'style'=>'width:100%','id' =>'modal-statuslabel_types', 'aria-label'=>'status_id')) }}
<x-input.select
name="status_id"
id="modal-statuslabel_types"
:options="$statusLabel_list"
style="width: 100%"
aria-label="status_id"
/>
{!! $errors->first('status_id', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
</div>
@include ('partials.forms.edit.location-select', ['translated_name' => trans('general.location'), 'fieldname' => 'location_id', 'help_text' => ($asset->defaultLoc) ? trans('general.checkin_to_diff_location', ['default_location' => $asset->defaultLoc->name]) : null, 'hide_location_radio' => true])
<x-input.location-select
:label="trans('general.location')"
name="location_id"
:help_text="($asset->defaultLoc) ? trans('general.checkin_to_diff_location', ['default_location' => $asset->defaultLoc->name]) : null"
:selected="old('location_id')"
/>
<!-- Update actual location -->
<div class="form-group">
<div class="col-md-9 col-md-offset-3">
<label class="form-control">
{{ Form::radio('update_default_location', '1', old('update_default_location'), ['checked'=> 'checked', 'aria-label'=>'update_default_location']) }}
{{ trans('admin/hardware/form.asset_location') }}
</label>
<label class="form-control">
{{ Form::radio('update_default_location', '0', old('update_default_location'), ['aria-label'=>'update_default_location']) }}
{{ trans('admin/hardware/form.asset_location_update_default_current') }}
</label>
</div>
</div> <!--/form-group-->
<!-- Checkout/Checkin Date -->
<div class="form-group{{ $errors->has('checkin_at') ? ' has-error' : '' }}">
@ -154,4 +179,4 @@
</div>
</div>
@stop
@stop

View file

@ -82,7 +82,13 @@
{{ trans('admin/hardware/form.status') }}
</label>
<div class="col-md-7 required">
{{ Form::select('status_id', $statusLabel_list, $asset->status_id, array('class'=>'select2', 'style'=>'width:100%','', 'aria-label'=>'status_id')) }}
<x-input.select
name="status_id"
:options="$statusLabel_list"
:selected="$asset->status_id"
style="width: 100%;"
aria-label="status_id"
/>
{!! $errors->first('status_id', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
</div>

View file

@ -47,7 +47,13 @@
{{ trans('admin/hardware/form.status') }}
</label>
<div class="col-md-7">
{{ Form::select('status_id', $statusLabel_list, '', array('class'=>'select2', 'style'=>'width:100%','', 'aria-label'=>'status_id')) }}
<x-input.select
name="status_id"
id="status_id"
:options="$statusLabel_list"
style="width:100%"
aria-label="status_id"
/>
{!! $errors->first('status_id', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
</div>

View file

@ -726,15 +726,21 @@
@endphp
@if ($fieldSize>0)
<span id="text-{{ $field->id }}-to-hide">{{ str_repeat('*', $fieldSize) }}</span>
<span class="js-copy-{{ $field->id }} hidden-print" id="text-{{ $field->id }}-to-show" style="font-size: 0px;">
@if (($field->format=='URL') && ($asset->{$field->db_column_name()}!=''))
<a href="{{ Helper::gracefulDecrypt($field, $asset->{$field->db_column_name()}) }}" target="_new">{{ Helper::gracefulDecrypt($field, $asset->{$field->db_column_name()}) }}</a>
@if (($field->format=='URL') && ($asset->{$field->db_column_name()}!=''))
<span class="js-copy-{{ $field->id }} hidden-print"
id="text-{{ $field->id }}-to-show"
style="font-size: 0px;"><a
href="{{ Helper::gracefulDecrypt($field, $asset->{$field->db_column_name()}) }}"
target="_new">{{ Helper::gracefulDecrypt($field, $asset->{$field->db_column_name()}) }}</a></span>
@elseif (($field->format=='DATE') && ($asset->{$field->db_column_name()}!=''))
{{ \App\Helpers\Helper::gracefulDecrypt($field, \App\Helpers\Helper::getFormattedDateObject($asset->{$field->db_column_name()}, 'date', false)) }}
<span class="js-copy-{{ $field->id }} hidden-print"
id="text-{{ $field->id }}-to-show"
style="font-size: 0px;">{{ \App\Helpers\Helper::gracefulDecrypt($field, \App\Helpers\Helper::getFormattedDateObject($asset->{$field->db_column_name()}, 'date', false)) }}</span>
@else
{{ Helper::gracefulDecrypt($field, $asset->{$field->db_column_name()}) }}
<span class="js-copy-{{ $field->id }} hidden-print"
id="text-{{ $field->id }}-to-show"
style="font-size: 0px;">{{ Helper::gracefulDecrypt($field, $asset->{$field->db_column_name()}) }}</span>
@endif
</span>
<i class="fa-regular fa-clipboard js-copy-link hidden-print" data-clipboard-target=".js-copy-{{ $field->id }}" aria-hidden="true" data-tooltip="true" data-placement="top" title="{{ trans('general.copy_to_clipboard') }}">
<span class="sr-only">{{ trans('general.copy_to_clipboard') }}</span>
</i>
@ -957,7 +963,7 @@
</strong>
</div>
<div class="col-md-9">
{{ Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date) }}
{{ (int) Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date, true) }}
{{ trans('admin/hardware/form.months') }}
</div>

View file

@ -33,6 +33,7 @@
data-pagination="true"
data-search="true"
data-side-pagination="server"
data-footer-style="footerStyle"
data-show-columns="true"
data-show-fullscreen="true"
data-show-export="true"

View file

@ -4,7 +4,16 @@
{{ trans('admin/models/general.fieldset') }}
</label>
<div class="col-md-5">
{{ Form::select('fieldset_id', Helper::customFieldsetList(), old('fieldset_id', $fieldset_id), array('class'=>'select2 js-fieldset-field livewire-select2', 'style'=>'width:100%; min-width:350px', 'aria-label'=>'custom_fieldset', 'data-livewire-component' => $this->getId())) }}
<x-input.select
name="fieldset_id"
id="fieldset_id"
:options="Helper::customFieldsetList()"
:selected="old('fieldset_id', $fieldset_id)"
:for-livewire="true"
class="js-fieldset-field"
style="width:100%; min-width:350px;"
aria-label="custom_fieldset"
/>
{!! $errors->first('custom_fieldset', '<span class="alert-msg" aria-hidden="true"><br><i class="fas fa-times"></i> :message</span>') !!}
</div>
<div class="col-md-3">

View file

@ -155,15 +155,20 @@
</label>
<div class="col-md-9 col-xs-12">
{{ Form::select('typeOfImport', $importTypes, $typeOfImport, [
'id' => 'import_type',
'class' => 'livewire-select2',
'style' => 'min-width: 350px',
'data-placeholder' => trans('general.select_var', ['thing' => trans('general.import_type')]),
'placeholder' => '', //needed so that the form-helper will put an empty option first
'data-minimum-results-for-search' => '-1', // Remove this if the list gets long enough that we need to search
'data-livewire-component' => $this->getId()
]) }}
<x-input.select
name="typeOfImport"
id="import_type"
:options="$importTypes"
:selected="$typeOfImport"
:for-livewire="true"
:include-empty="true"
:data-placeholder="trans('general.select_var', ['thing' => trans('general.import_type')])"
{{--placeholder needed so that the form-helper will put an empty option first--}}
placeholder=""
{{--Remove this if the list gets long enough that we need to search--}}
data-minimum-results-for-search="-1"
style="min-width: 350px;"
/>
@if ($typeOfImport === 'asset' && $snipeSettings->auto_increment_assets == 0)
<p class="help-block">
{{ trans('general.auto_incrementing_asset_tags_disabled_so_tags_required') }}
@ -238,17 +243,22 @@
<label for="field_map.{{ $index }}" class="col-md-3 control-label text-right">{{ $header }}</label>
<div class="col-md-4">
{{ Form::select('field_map.'.$index, $columnOptions[$typeOfImport], @$field_map[$index],
[
'class' => 'mappings livewire-select2',
'placeholder' => trans('general.importer.do_not_import'),
'style' => 'min-width: 100%',
'data-livewire-component' => $this->getId()
],[
'-' => ['disabled' => true] // this makes the "-----" line unclickable
])
}}
<x-input.select
:name="'field_map.'.$index"
:for-livewire="true"
:placeholder="trans('general.importer.do_not_import')"
class="mappings"
style="min-width: 100%;"
>
<option selected="selected" value="">Do Not Import</option>
@foreach($columnOptions[$typeOfImport] as $key => $value)
<option
value="{{ $key }}"
@selected(@$field_map[$index] === $key)
@disabled($key === '-')
>{{ $value }}</option>
@endforeach
</x-input.select>
</div>
@if (($this->activeFile->first_row) && (array_key_exists($index, $this->activeFile->first_row)))
<div class="col-md-5">

View file

@ -66,13 +66,17 @@
</label>
</div>
<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'),'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'),'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
<x-input.select
name="webhook_selected"
id="select2"
:options="['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')]"
:selected="old('webhook_selected', $webhook_selected)"
:disabled="Helper::isDemoMode()"
data-minimum-results-for-search="-1"
class="form-control"
style="width:100%"
aria-label="webhook_selected"
/>
</div>
</div>

View file

@ -157,7 +157,42 @@
<div class="tab-content">
<div class="tab-pane active" id="users">
<div class="tab-pane active" id="assets">
<h2 class="box-title">{{ trans('admin/locations/message.current_location') }}</h2>
<div class="table table-responsive">
@include('partials.asset-bulk-actions')
<table
data-columns="{{ \App\Presenters\AssetPresenter::dataTableLayout() }}"
data-cookie-id-table="assetsListingTable"
data-pagination="true"
data-id-table="assetsListingTable"
data-search="true"
data-side-pagination="server"
data-show-columns="true"
data-show-export="true"
data-show-refresh="true"
data-sort-order="asc"
data-toolbar="#assetsBulkEditToolbar"
data-bulk-button-id="#bulkAssetEditButton"
data-bulk-form-id="#assetsBulkForm"
data-click-to-select="true"
id="assetsListingTable"
class="table table-striped snipe-table"
data-url="{{route('api.assets.index', ['location_id' => $location->id]) }}"
data-export-options='{
"fileName": "export-locations-{{ str_slug($location->name) }}-assets-{{ date('Y-m-d') }}",
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
}'>
</table>
</div><!-- /.table-responsive -->
</div><!-- /.tab-pane -->
<div class="tab-pane" id="users">
<h2 class="box-title">{{ trans('general.users') }}</h2>
<div class="table table-responsive">
@include('partials.users-bulk-actions')
@ -188,37 +223,6 @@
</div><!-- /.table-responsive -->
</div><!-- /.tab-pane -->
<div class="tab-pane" id="assets">
<h2 class="box-title">{{ trans('admin/locations/message.current_location') }}</h2>
<div class="table table-responsive">
@include('partials.asset-bulk-actions')
<table
data-columns="{{ \App\Presenters\AssetPresenter::dataTableLayout() }}"
data-cookie-id-table="assetsListingTable"
data-pagination="true"
data-id-table="assetsListingTable"
data-search="true"
data-side-pagination="server"
data-show-columns="true"
data-show-export="true"
data-show-refresh="true"
data-sort-order="asc"
data-toolbar="#assetsBulkEditToolbar"
data-bulk-button-id="#bulkAssetEditButton"
data-bulk-form-id="#assetsBulkForm"
data-click-to-select="true"
id="assetsListingTable"
class="table table-striped snipe-table"
data-url="{{route('api.assets.index', ['location_id' => $location->id]) }}"
data-export-options='{
"fileName": "export-locations-{{ str_slug($location->name) }}-assets-{{ date('Y-m-d') }}",
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
}'>
</table>
</div><!-- /.table-responsive -->
</div><!-- /.tab-pane -->
<div class="tab-pane" id="assets_assigned">
<h2 class="box-title">
@ -464,7 +468,16 @@
@endif
<div class="col-md-12">
<ul class="list-unstyled" style="line-height: 20px; padding-bottom: 20px;">
<ul class="list-unstyled" style="line-height: 22px; padding-bottom: 20px;">
@if ($location->notes)
<li>
<strong>{{ trans('general.notes') }}</strong>:
{!! nl2br(Helper::parseEscapedMarkedownInline($location->notes)) !!}
</li>
@endif
@if ($location->address!='')
<li>{{ $location->address }}</li>
@endif
@ -484,6 +497,7 @@
<li>{{ trans('admin/locations/table.ldap_ou') }}: {{ $location->ldap_ou }}</li>
@endif
@if ((($location->address!='') && ($location->city!='')) || ($location->state!='') || ($location->country!=''))
<li>
<a href="https://maps.google.com/?q={{ urlencode($location->address.','. $location->city.','.$location->state.','.$location->country.','.$location->zip) }}" target="_blank">

View file

@ -1,6 +1,14 @@
<!-- partials/modals/partials/fieldset-select.blade.php -->
<div class="dynamic-form-row">
<div class="col-md-4 col-xs-12"><label for="modal-fieldset_id">{{ trans('admin/models/general.fieldset') }}:</label></div>
<div class="col-md-8 col-xs-12">{{ Form::select('fieldset_id', Helper::customFieldsetList(),old('fieldset_id'), array('class'=>'select2', 'id'=>'modal-fieldset_id', 'style'=>'width:100%;')) }}</div>
<div class="col-md-8 col-xs-12">
<x-input.select
name="fieldset_id"
id="modal-fieldset_id"
:options="Helper::customFieldsetList()"
:selected="old('fieldset_id')"
style="width:100%;"
/>
</div>
</div>
<!-- partials/modals/partials/fieldset-select.blade.php -->
<!-- partials/modals/partials/fieldset-select.blade.php -->

View file

@ -16,7 +16,15 @@
<div class="dynamic-form-row">
<div class="col-md-3 col-xs-12"><label for="modal-type">{{ trans('admin/statuslabels/table.status_type') }}:
</label></div>
<div class="col-md-8 col-xs-12">{{ Form::select('type', $statuslabel_types, '', array('class'=>'select2', 'style'=>'width:100%','id' =>'modal-type', 'required',)) }}</div>
<div class="col-md-8 col-xs-12">
<x-input.select
name="type"
id="modal-type"
:options="$statuslabel_types"
required
style="width:100%;"
/>
</div>
</div>
</form>
</div>

View file

@ -42,10 +42,10 @@
@include ('partials.forms.edit.location-profile-select', ['translated_name' => trans('general.location'), 'fieldname' => 'location_id'])
</div>
<div class="dynamic-form-row">
@include('partials.forms.edit.name-first', [ 'required' => 'true', 'class' => 'col-md-8 col-xs-12-pull', 'style' => 'width:67%;'])
@include('partials.forms.edit.name-first', ['value' => '', 'required' => 'true', 'class' => 'col-md-8 col-xs-12-pull', 'style' => 'width:67%;'])
</div>
<div class="dynamic-form-row">
@include('partials.forms.edit.name-last', ['required' => 'true', 'class' => 'col-md-8 col-xs-12-pull', 'style' => 'width:67%;'])
@include('partials.forms.edit.name-last', ['value' => '', 'required' => 'true', 'class' => 'col-md-8 col-xs-12-pull', 'style' => 'width:67%;'])
</div>
<div class="dynamic-form-row">
@include('partials.forms.edit.email')

View file

@ -62,7 +62,13 @@
{{ trans('admin/models/general.fieldset') }}
</label>
<div class="col-md-7">
{{ Form::select('fieldset_id', $fieldset_list , old('fieldset_id', 'NC'), array('class'=>'select2 js-fieldset-field', 'style'=>'width:350px')) }}
<x-input.select
name="fieldset_id"
:options="$fieldset_list"
:selected="old('fieldset_id', 'NC')"
class="js-fieldset-field"
style="width:350px"
/>
{!! $errors->first('fieldset_id', '<span class="alert-msg" aria-hidden="true"><br><i class="fas fa-times"></i> :message</span>') !!}
</div>
</div>
@ -74,7 +80,12 @@
{{ trans('general.depreciation') }}
</label>
<div class="col-md-7">
{{ Form::select('depreciation_id', $depreciation_list , old('depreciation_id', 'NC'), array('class'=>'select2', 'style'=>'width:350px')) }}
<x-input.select
name="depreciation_id"
:options="$depreciation_list"
:selected="old('depreciation_id', 'NC')"
style="width:350px"
/>
{!! $errors->first('depreciation_id', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
</div>

View file

@ -17,8 +17,13 @@
@if ($field->element=='listbox')
<!-- Listbox -->
{{ Form::select($field->db_column_name(), $field->formatFieldValuesAsArray(),
old($field->db_column_name(),(isset($item) ? Helper::gracefulDecrypt($field, $item->{$field->db_column_name()}) : $field->defaultValue($model->id))), ['class' => 'format select2 form-control', ($field->pivot->required=='1' ? ' required' : '') ]) }}
<x-input.select
:name="$field->db_column_name()"
:options="$field->formatFieldValuesAsArray()"
:selected="old($field->db_column_name(), (isset($item) ? Helper::gracefulDecrypt($field, $item->{$field->db_column_name()}) : $field->defaultValue($model->id)))"
:required="$field->pivot->required == '1'"
class="format form-control"
/>
@elseif ($field->element=='textarea')
<!-- Textarea -->

View file

@ -24,8 +24,12 @@
@if ($field->element!='text')
<!-- Listbox -->
@if ($field->element=='listbox')
{{ Form::select($field->db_column_name(), $field->formatFieldValuesAsArray(),
old($field->db_column_name(),(isset($item) ? Helper::gracefulDecrypt($field, $item->{$field->db_column_name()}) : $field->defaultValue($model->id))), ['class'=>'format select2 form-control']) }}
<x-input.select
:name="$field->db_column_name()"
:options="$field->formatFieldValuesAsArray()"
:selected="old($field->db_column_name(),(isset($item) ? Helper::gracefulDecrypt($field, $item->{$field->db_column_name()}) : $field->defaultValue($model->id)))"
class="format form-control"
/>
@elseif ($field->element=='textarea')
@if($field->is_unique)

View file

@ -45,6 +45,7 @@
data-search="true"
data-show-footer="true"
data-side-pagination="server"
data-footer-style="footerStyle"
data-show-columns="true"
data-toolbar="#modelsBulkEditToolbar"
data-bulk-button-id="#bulkModelsEditButton"

View file

@ -153,23 +153,11 @@
<ul class="list-unstyled" style="line-height: 25px;">
@if ($model->category)
<li>{{ trans('general.category') }}:
<li>
<strong>{{ trans('general.category') }}</strong>:
<a href="{{ route('categories.show', $model->category->id) }}">{{ $model->category->name }}</a>
</li>
@endif
@if ($model->created_at)
<li>{{ trans('general.created_at') }}:
{{ Helper::getFormattedDateObject($model->created_at, 'datetime', false) }}
</li>
@endif
@if ($model->adminuser)
<li>{{ trans('general.created_by') }}:
{{ $model->adminuser->present()->name() }}
</li>
@endif
@if ($model->deleted_at)
<li>
<strong>
@ -183,14 +171,15 @@
@endif
@if ($model->min_amt)
<li>{{ trans('general.min_amt') }}:
<li>
<strong>{{ trans('general.min_amt') }}</strong>:
{{$model->min_amt }}
</li>
@endif
@if ($model->manufacturer)
<li>
{{ trans('general.manufacturer') }}:
<strong>{{ trans('general.manufacturer') }}</strong>:
@can('view', \App\Models\Manufacturer::class)
<a href="{{ route('manufacturers.show', $model->manufacturer->id) }}">
{{ $model->manufacturer->name }}
@ -228,46 +217,56 @@
@endif
@if ($model->model_number)
<li>
{{ trans('general.model_no') }}:
<strong>{{ trans('general.model_no') }}</strong>:
{{ $model->model_number }}
</li>
@endif
@if ($model->depreciation)
<li>
{{ trans('general.depreciation') }}:
<strong>{{ trans('general.depreciation') }}</strong>:
{{ $model->depreciation->name }} ({{ $model->depreciation->months.' '.trans('general.months')}})
</li>
@endif
@if ($model->eol)
<li>{{ trans('general.eol') }}:
<li>
<strong>{{ trans('general.eol') }}</strong>:
{{ $model->eol .' '. trans('general.months') }}
</li>
@endif
@if ($model->fieldset)
<li>{{ trans('admin/models/general.fieldset') }}:
<li>
<strong>{{ trans('admin/models/general.fieldset') }}</strong>:
<a href="{{ route('fieldsets.show', $model->fieldset->id) }}">{{ $model->fieldset->name }}</a>
</li>
@endif
@if ($model->notes)
<li>
{{ trans('general.notes') }}:
<strong>{{ trans('general.notes') }}</strong>:
{!! nl2br(Helper::parseEscapedMarkedownInline($model->notes)) !!}
</li>
@endif
</ul>
@if ($model->created_at)
<li>
<strong>{{ trans('general.created_at') }}</strong>:
{{ Helper::getFormattedDateObject($model->created_at, 'datetime', false) }}
</li>
@endif
@if ($model->note)
Notes:
<p>
{!! $model->present()->note() !!}
</p>
@endif
</div>
@if ($model->adminuser)
<li>
<strong>{{ trans('general.created_by') }}</strong>:
{{ $model->adminuser->present()->name() }}
</li>
@endif
</ul>
</div>
</div>
</div>
@can('update', \App\Models\AssetModel::class)

View file

@ -9,7 +9,7 @@
@php
$next_audit_date = Helper::getFormattedDateObject($asset->next_audit_date, 'date', false);
$last_audit_date = Helper::getFormattedDateObject($asset->last_audit_date, 'date', false);
$diff = Carbon::parse(Carbon::now())->diffInDays($asset->next_audit_date, false);
$diff = (int) Carbon::parse(Carbon::now())->diffInDays($asset->next_audit_date, true);
$icon = ($diff <= 7) ? '🚨' : (($diff <= 14) ? '⚠️' : ' ');
@endphp
|{{ $icon }}| [{{ $asset->present()->name }}]({{ route('hardware.show', $asset->id) }}) | {{ $last_audit_date }}| {{ $next_audit_date }} | {{ $diff }} | {{ ($asset->supplier ? e($asset->supplier->name) : '') }}|{{ ($asset->assignedTo ? $asset->assignedTo->present()->name() : '') }}|{{ $asset->notes }}

View file

@ -13,6 +13,7 @@
<script nonce="{{ csrf_token() }}">
$(function () {
var blockedFields = "searchable,sortable,switchable,title,visible,formatter,class".split(",");
var keyBlocked = function(key) {
@ -241,7 +242,35 @@
});
// This specifies the footer columns that should have special styles associated
// (usually numbers)
window.footerStyle = column => ({
remaining: {
classes: 'text-padding-number-footer-cell'
},
qty: {
classes: 'text-padding-number-footer-cell',
},
purchase_cost: {
classes: 'text-padding-number-footer-cell'
},
checkouts_count: {
classes: 'text-padding-number-footer-cell'
},
assets_count: {
classes: 'text-padding-number-footer-cell'
},
seats: {
classes: 'text-padding-number-footer-cell'
},
free_seats_count: {
classes: 'text-padding-number-footer-cell'
},
}[column.field]);
// This only works for model index pages because it uses the row's model ID
function genericRowLinkFormatter(destination) {
@ -513,7 +542,7 @@
if (value.assigned_to_self == true){
return '<button class="btn btn-danger btn-sm disabled" data-tooltip="true" title="Cancel this item request">{{ trans('button.cancel') }}</button>';
} else if (value.available_actions.cancel == true) {
return '<form action="{{ config('app.url') }}/account/request-asset/'+ value.id + '" method="POST">@csrf<button class="btn btn-danger btn-sm" data-tooltip="true" title="Cancel this item request">{{ trans('button.cancel') }}</button></form>';
return '<form action="{{ config('app.url') }}/account/request-asset/' + value.id + '/cancel" method="POST">@csrf<button class="btn btn-danger btn-sm" data-tooltip="true" title="Cancel this item request">{{ trans('button.cancel') }}</button></form>';
} else if (value.available_actions.request == true) {
return '<form action="{{ config('app.url') }}/account/request-asset/'+ value.id + '" method="POST">@csrf<button class="btn btn-primary btn-sm" data-tooltip="true" title="{{ trans('general.request_item') }}">{{ trans('button.request') }}</button></form>';
}
@ -664,14 +693,16 @@
function minAmtFormatter(row, value) {
if ((row) && (row!=undefined)) {
if (value.free_seats_count <= value.min_amt) {
return '<span class="text-danger text-bold" data-tooltip="true" title="{{ trans('admin/licenses/general.below_threshold_short') }}">' + value.min_amt + '</span>';
if (value.remaining <= value.min_amt) {
return '<span class="text-danger text-bold" data-tooltip="true" title="{{ trans('admin/licenses/general.below_threshold_short') }}"><x-icon type="warning" class="text-yellow" /> ' + value.min_amt + '</span>';
}
return value.min_amt
}
return '--';
}
// Create a linked phone number in the table list
function phoneFormatter(value) {
@ -906,6 +937,19 @@
return parseFloat(decimalfixed);
}
function qtySumFormatter(data) {
var currentField = this.field;
var total = 0;
var fieldname = this.field;
$.each(data, function() {
var r = this;
total += this[currentField];
});
return total;
}
function sumFormatter(data) {
if (Array.isArray(data)) {
var field = this.field;

View file

@ -1,8 +0,0 @@
<!-- Category -->
<div class="form-group {{ $errors->has('category_id') ? ' has-error' : '' }}">
<label for="category_id" class="col-md-3 control-label">{{ trans('general.category') }}</label>
<div class="col-md-7 col-sm-12">
{{ Form::select('category_id', $category_list , old('category_id', $item->category_id), array('class'=>'select2', 'style'=>'width:100%', 'required' => Helper::checkIfRequired($item, 'category_id') ? true : '')) }}
{!! $errors->first('category_id', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
</div>

View file

@ -1,11 +0,0 @@
@if (\App\Models\Company::isCurrentUserAuthorized())
<div class="form-group {{ $errors->has('company_id') ? ' has-error' : '' }}">
<div class="col-md-3 control-label">
<label for="company_id" class="col-md-3 control-label">{{ trans('general.company') }}</label>
</div>
<div class="col-md-7 col-sm-12">
{{ Form::select('company_id', $company_list , old('company_id', $item->company_id), array('class'=>'select2', 'style'=>'width:100%', 'required' => Helper::checkIfRequired($item, 'company_id') ? true : '')) }}
{!! $errors->first('company_id', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
</div>
@endif

View file

@ -2,7 +2,14 @@
<div class="form-group {{ $errors->has('depreciation_id') ? ' has-error' : '' }}">
<label for="depreciation_id" class="col-md-3 control-label">{{ trans('general.depreciation') }}</label>
<div class="col-md-7">
{{ Form::select('depreciation_id', $depreciation_list , old('depreciation_id', $item->depreciation_id), array('class'=>'select2', 'style'=>'width:350px', 'aria-label'=>'depreciation_id')) }}
<x-input.select
name="depreciation_id"
id="depreciation_id"
:options="$depreciation_list"
:selected="old('depreciation_id', $item->depreciation_id)"
style="width:350px;"
aria-label="depreciation_id"
/>
{!! $errors->first('depreciation_id', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
</div>

View file

@ -1,8 +0,0 @@
<!-- Location -->
<div class="form-group {{ $errors->has('location_id') ? ' has-error' : '' }}">
<label for="location_id" class="col-md-3 control-label">{{ trans('general.location') }}</label>
<div class="col-md-7 col-sm-12">
{{ Form::select('location_id', $location_list , old('location_id', $item->location_id), array('class'=>'select2', 'style'=>'width:350px')) }}
{!! $errors->first('location_id', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
</div>

View file

@ -3,7 +3,14 @@
<label for="asset_maintenance_type" class="col-md-3 control-label">{{ trans('admin/asset_maintenances/form.asset_maintenance_type') }}
</label>
<div class="col-md-7">
{{ Form::select('asset_maintenance_type', $assetMaintenanceType , old('asset_maintenance_type', $item->asset_maintenance_type), ['class'=>'select2', 'aria-label'=>'asset_maintenance_type', 'required' => Helper::checkIfRequired($item, 'asset_maintenance_type') ? true : '', 'style'=> 'width:100%;']) }}
<x-input.select
name="asset_maintenance_type"
:options="$assetMaintenanceType"
:selected="old('asset_maintenance_type', $item->asset_maintenance_type)"
:required="Helper::checkIfRequired($item, 'asset_maintenance_type')"
style="width:100%;"
aria-label="asset_maintenance_type"
/>
{!! $errors->first('asset_maintenance_type', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
</div>

Some files were not shown because too many files have changed in this diff Show more