Compare commits
147 Commits
use-transf
...
update-js-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d3d1724bb | ||
|
|
257d58c236 | ||
|
|
015f3d936c | ||
|
|
18d2a0ffd7 | ||
|
|
24afde0e46 | ||
|
|
8499faa55a | ||
|
|
c60dd809b8 | ||
|
|
297b8e33f2 | ||
|
|
b670b2014c | ||
|
|
440e969f52 | ||
|
|
14b79f2f1c | ||
|
|
00cf49a61f | ||
|
|
4f534e0e84 | ||
|
|
83a19fbbbf | ||
|
|
610cb884fc | ||
|
|
ba92cec62b | ||
|
|
d92e961a52 | ||
|
|
b13e74756a | ||
|
|
4ef3072766 | ||
|
|
e96e2461d3 | ||
|
|
7a2e2be169 | ||
|
|
8d2a5a7e4a | ||
|
|
b7b0e4fab5 | ||
|
|
a624a79b30 | ||
|
|
313135da6f | ||
|
|
58d27d1247 | ||
|
|
edfb28168f | ||
|
|
8d0e03bb06 | ||
|
|
855f6f77cf | ||
|
|
6236cffe14 | ||
|
|
322a71fbb8 | ||
|
|
4d9f8476f3 | ||
|
|
d7d93b14b2 | ||
|
|
d1af3ece6e | ||
|
|
8153b20984 | ||
|
|
a50f605c29 | ||
|
|
daf23edd10 | ||
|
|
2eaaeb8259 | ||
|
|
a02c62d62c | ||
|
|
e0232a8e84 | ||
|
|
6ea5693b2f | ||
|
|
030c2114d1 | ||
|
|
2cb18e3668 | ||
|
|
cd9f8be563 | ||
|
|
a02792e9bf | ||
|
|
41bb422244 | ||
|
|
54663d3342 | ||
|
|
2529f7369f | ||
|
|
909c33dccf | ||
|
|
1adc9f1aa9 | ||
|
|
49da9e58fd | ||
|
|
f3e288d078 | ||
|
|
988000952e | ||
|
|
6537f3794b | ||
|
|
d31718ba8a | ||
|
|
9dd4bc5fa8 | ||
|
|
df5f1bd522 | ||
|
|
ddffab9169 | ||
|
|
0c34073582 | ||
|
|
14674947cb | ||
|
|
51bccdbd66 | ||
|
|
f0fbb3cf36 | ||
|
|
0cc47aacbe | ||
|
|
fafd592290 | ||
|
|
40e754b8c3 | ||
|
|
483301db7a | ||
|
|
218606fbd6 | ||
|
|
c601b8e62c | ||
|
|
2bd68ec991 | ||
|
|
66842648ed | ||
|
|
ce54b9a7b5 | ||
|
|
8a5f6d2a5d | ||
|
|
1d86a5476f | ||
|
|
ca4d3f6bce | ||
|
|
2812f2ce92 | ||
|
|
5c623db798 | ||
|
|
edaf005fe1 | ||
|
|
4f6e407247 | ||
|
|
e30881239c | ||
|
|
bbde2cc4b2 | ||
|
|
16d18c79d7 | ||
|
|
a0d2cb8a03 | ||
|
|
1bb5dc7e69 | ||
|
|
58759acfe4 | ||
|
|
0cd5136052 | ||
|
|
b3c6fe5369 | ||
|
|
599718f84e | ||
|
|
d9a5452388 | ||
|
|
0fe49e04bf | ||
|
|
a98d3fb4dc | ||
|
|
8c670d1832 | ||
|
|
c232f490bc | ||
|
|
c7280953dd | ||
|
|
8f4c606c64 | ||
|
|
6740afab42 | ||
|
|
5df22b3e6a | ||
|
|
3d9d18a0d5 | ||
|
|
fc469707a3 | ||
|
|
77fdc370c7 | ||
|
|
301290fb6d | ||
|
|
07fffe2f79 | ||
|
|
0227a63fa5 | ||
|
|
27764b863c | ||
|
|
032fd75f9e | ||
|
|
0bf4f861f3 | ||
|
|
fd8f90cb52 | ||
|
|
b6c6b025c8 | ||
|
|
3d89e98d1f | ||
|
|
7c5110ed5d | ||
|
|
0a474f48ad | ||
|
|
c409bfd5be | ||
|
|
39d5d5b2e0 | ||
|
|
8a80d9009d | ||
|
|
f62b5df566 | ||
|
|
214757ab0b | ||
|
|
f130186b37 | ||
|
|
2244eebc3b | ||
|
|
4176792f2d | ||
|
|
1e6cef52c9 | ||
|
|
a0f4f30a50 | ||
|
|
4cbf6ac393 | ||
|
|
af7425d8e6 | ||
|
|
3fea909d3f | ||
|
|
7c37d40677 | ||
|
|
3a97c27350 | ||
|
|
e0516a52a8 | ||
|
|
a85ec6efb3 | ||
|
|
3795c74814 | ||
|
|
27954dc6d3 | ||
|
|
68c4187a09 | ||
|
|
b9834231f3 | ||
|
|
2be343ea1c | ||
|
|
109fe1b62c | ||
|
|
63d691a63c | ||
|
|
6f57d6b876 | ||
|
|
e0bad99ea1 | ||
|
|
e39eb09cfb | ||
|
|
64d397c3f3 | ||
|
|
465ac1d1e1 | ||
|
|
18d6becebc | ||
|
|
3bbd0fdbcd | ||
|
|
8214b11da5 | ||
|
|
36090bf83e | ||
|
|
bffb2fe82f | ||
|
|
500cbf5d92 | ||
|
|
c8b213c190 | ||
|
|
942de9dce5 |
@@ -168,6 +168,7 @@ AWS_DEFAULT_REGION=null
|
||||
LOGIN_MAX_ATTEMPTS=5
|
||||
LOGIN_LOCKOUT_DURATION=60
|
||||
RESET_PASSWORD_LINK_EXPIRES=900
|
||||
INVITE_PASSWORD_LINK_EXPIRES=1500
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: MISC
|
||||
|
||||
@@ -174,6 +174,7 @@ LOGIN_AUTOCOMPLETE=false
|
||||
RESET_PASSWORD_LINK_EXPIRES=15
|
||||
PASSWORD_CONFIRM_TIMEOUT=10800
|
||||
PASSWORD_RESET_MAX_ATTEMPTS_PER_MIN=50
|
||||
INVITE_PASSWORD_LINK_EXPIRES=1500
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: MISC
|
||||
|
||||
2
.github/workflows/codacy-analysis.yml
vendored
2
.github/workflows/codacy-analysis.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
|
||||
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
|
||||
- name: Run Codacy Analysis CLI
|
||||
uses: codacy/codacy-analysis-cli-action@v4.4.5
|
||||
uses: codacy/codacy-analysis-cli-action@v4.4.7
|
||||
with:
|
||||
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
|
||||
# You can also omit the token and run the tools that support default configurations
|
||||
|
||||
68
app/Console/Commands/CleanIncorrectCheckoutAcceptances.php
Normal file
68
app/Console/Commands/CleanIncorrectCheckoutAcceptances.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\CheckoutAcceptance;
|
||||
use App\Models\LicenseSeat;
|
||||
use App\Models\User;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class CleanIncorrectCheckoutAcceptances extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'snipeit:clean-checkout-acceptances';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = "Delete checkout acceptances for checkouts to non-users";
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$deletions = 0;
|
||||
$skips = 0;
|
||||
|
||||
// This walks *every* checkoutacceptance. That's gnarly. But necessary
|
||||
$this->withProgressBar(CheckoutAcceptance::all(), function ($checkoutAcceptance) use (&$deletions, &$skips) {
|
||||
$item = $checkoutAcceptance->checkoutable;
|
||||
$checkout_to_id = $checkoutAcceptance->assigned_to_id;
|
||||
if(is_null($item)) {
|
||||
$this->info("'Checkoutable' Item is null, going to next record");
|
||||
return; //'false' allegedly breaks execution entirely, so 'true' maybe doesn't? hrm. just straight return maybe?
|
||||
}
|
||||
if(get_class($item) == LicenseSeat::class) {
|
||||
$item = $item->license;
|
||||
}
|
||||
foreach($item->assetlog()->where('action_type','checkout')->get() as $assetlog) {
|
||||
if ($assetlog->target_id == $checkout_to_id && $assetlog->target_type != User::class) {
|
||||
//We have a checkout-to an ID for a non-User, which matches to an ID in the checkout_acceptances table
|
||||
|
||||
//now, let's compare the _times_ - are they close?
|
||||
//I'm picking `created_at` over `action_date` because I'm more interested in when the actionlogs
|
||||
//were _created_, not when they were alleged to have happened - those created_at times need to be within 'X' seconds of
|
||||
//each other (currently 5)
|
||||
if ($assetlog->created_at->diffInSeconds($checkoutAcceptance->created_at, true) <= 5) { //we're allowing for five _ish_ seconds of slop
|
||||
$deletions++;
|
||||
$checkoutAcceptance->forceDelete(); // HARD delete this record; it should have never been
|
||||
return;
|
||||
} else {
|
||||
//$this->info("The two records are too far apart");
|
||||
}
|
||||
} else {
|
||||
//$this->info("No match! checkout to id: " . $checkout_to_id." target_id: ".$assetlog->target_id." target_type: ".$assetlog->target_type);
|
||||
}
|
||||
}
|
||||
$skips++;
|
||||
});
|
||||
$this->error("Final deletion count: $deletions, and skip count: $skips");
|
||||
}
|
||||
}
|
||||
@@ -133,6 +133,15 @@ class Handler extends ExceptionHandler
|
||||
// This is traaaaash but it handles models that are not found while using route model binding :(
|
||||
// The only alternative is to set that at *each* route, which is crazypants
|
||||
if ($e instanceof \Illuminate\Database\Eloquent\ModelNotFoundException) {
|
||||
$ids = method_exists($e, 'getIds') ? $e->getIds() : [];
|
||||
|
||||
if (in_array('bulkedit', $ids, true)) {
|
||||
$error_array = session()->get('bulk_asset_errors');
|
||||
return redirect()
|
||||
->route('hardware.bulkedit')
|
||||
->withErrors($error_array, 'bulk_asset_errors')
|
||||
->withInput();
|
||||
}
|
||||
|
||||
// This gets the MVC model name from the exception and formats in a way that's less fugly
|
||||
$model_name = strtolower(implode(" ", preg_split('/(?=[A-Z])/', last(explode('\\', $e->getModel())))));
|
||||
|
||||
@@ -93,6 +93,7 @@ class UploadedFilesController extends Controller
|
||||
'id',
|
||||
'filename',
|
||||
'action_type',
|
||||
'action_date',
|
||||
'note',
|
||||
'created_at',
|
||||
];
|
||||
|
||||
@@ -23,6 +23,7 @@ use App\Notifications\CurrentInventory;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
@@ -81,7 +82,12 @@ class UsersController extends Controller
|
||||
'users.autoassign_licenses',
|
||||
'users.website',
|
||||
|
||||
])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy', 'managesUsers', 'managedLocations', 'eulas')
|
||||
])->with('manager')
|
||||
->with('groups')
|
||||
->with('userloc')
|
||||
->with('company')
|
||||
->with('department')
|
||||
->with('createdBy')
|
||||
->withCount([
|
||||
'assets as assets_count' => function(Builder $query) {
|
||||
$query->withoutTrashed();
|
||||
@@ -475,10 +481,27 @@ class UsersController extends Controller
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager'));
|
||||
}
|
||||
|
||||
// check for permissions related fields and pull them out if the current user cannot edit them
|
||||
if (auth()->user()->can('canEditAuthFields', $user) && auth()->user()->can('editableOnDemo')) {
|
||||
|
||||
if ($request->filled('password')) {
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
|
||||
if ($request->filled('username')) {
|
||||
$user->username = $request->input('username');
|
||||
}
|
||||
|
||||
if ($request->filled('email')) {
|
||||
$user->email = $request->input('email');
|
||||
}
|
||||
|
||||
if ($request->filled('activated')) {
|
||||
$user->activated = $request->input('activated');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// We need to use has() instead of filled()
|
||||
// here because we need to overwrite permissions
|
||||
// if someone needs to null them out
|
||||
|
||||
@@ -227,7 +227,10 @@ class AssetsController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);
|
||||
session()->put(['redirect_option' => $request->get('redirect_option'),
|
||||
'checkout_to_type' => $request->get('checkout_to_type'),
|
||||
'other_redirect' => 'model' ]);
|
||||
|
||||
|
||||
|
||||
if ($successes) {
|
||||
|
||||
@@ -161,6 +161,7 @@ class BulkAssetsController extends Controller
|
||||
|
||||
$models = $assets->unique('model_id');
|
||||
$modelNames = [];
|
||||
|
||||
foreach($models as $model) {
|
||||
$modelNames[] = $model->model->name;
|
||||
}
|
||||
@@ -196,7 +197,6 @@ class BulkAssetsController extends Controller
|
||||
|
||||
case 'edit':
|
||||
$this->authorize('update', Asset::class);
|
||||
|
||||
return view('hardware/bulk')
|
||||
->with('assets', $asset_ids)
|
||||
->with('statuslabel_list', Helper::statusLabelList())
|
||||
@@ -224,11 +224,8 @@ class BulkAssetsController extends Controller
|
||||
$error_array = array();
|
||||
|
||||
// Get the back url from the session and then destroy the session
|
||||
$bulk_back_url = route('hardware.index');
|
||||
|
||||
if ($request->session()->has('bulk_back_url')) {
|
||||
$bulk_back_url = $request->session()->pull('bulk_back_url');
|
||||
}
|
||||
$bulk_back_url = $request->session()->pull('bulk_back_url', url()->previous());
|
||||
|
||||
$custom_field_columns = CustomField::all()->pluck('db_column')->toArray();
|
||||
|
||||
@@ -543,7 +540,13 @@ class BulkAssetsController extends Controller
|
||||
} // end asset foreach
|
||||
|
||||
if ($has_errors > 0) {
|
||||
return redirect($bulk_back_url)->with('bulk_asset_errors', $error_array);
|
||||
session()->put('bulkedit_ids', $request->input('ids'));
|
||||
session()->put('bulk_asset_errors',$error_array);
|
||||
|
||||
return redirect()
|
||||
->route('hardware.bulkedit')
|
||||
->with('bulk_asset_errors', $error_array)
|
||||
->withInput();
|
||||
}
|
||||
|
||||
return redirect($bulk_back_url)->with('success', trans('admin/hardware/message.update.success'));
|
||||
@@ -735,4 +738,33 @@ class BulkAssetsController extends Controller
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function bulkEditForm(): View|RedirectResponse
|
||||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
|
||||
$asset_ids = session()->pull('bulkedit_ids', []);
|
||||
|
||||
if (empty($asset_ids)) {
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.update.no_assets_selected'));
|
||||
}
|
||||
|
||||
$assets = Asset::with('model')->withTrashed()->whereIn('id', $asset_ids)->get();
|
||||
|
||||
if ($assets->isEmpty()) {
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.update.assets_do_not_exist_or_are_invalid'));
|
||||
}
|
||||
|
||||
$models = $assets->unique('model_id');
|
||||
$modelNames = [];
|
||||
foreach ($models as $model) {
|
||||
$modelNames[] = $model->model->name;
|
||||
}
|
||||
|
||||
return view('hardware/bulk')
|
||||
->with('assets', $asset_ids)
|
||||
->with('statuslabel_list', Helper::statusLabelList())
|
||||
->with('models', $models->pluck(['model']))
|
||||
->with('modelNames', $modelNames);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,15 +13,8 @@ use App\Models\Company;
|
||||
use App\Models\Group;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use App\Notifications\WelcomeNotification;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Redirect;
|
||||
use Str;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use App\Notifications\CurrentInventory;
|
||||
|
||||
@@ -130,7 +123,7 @@ class UsersController extends Controller
|
||||
}
|
||||
$user->permissions = json_encode($permissions_array);
|
||||
|
||||
// we have to invoke the
|
||||
// we have to invoke the form request here to handle image uploads
|
||||
app(ImageUploadRequest::class)->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
@@ -142,18 +135,6 @@ class UsersController extends Controller
|
||||
$user->groups()->sync([]);
|
||||
}
|
||||
|
||||
if (($request->input('email_user') == 1) && ($request->filled('email'))) {
|
||||
// Send the credentials through email
|
||||
$data = [];
|
||||
$data['email'] = e($request->input('email'));
|
||||
$data['username'] = e($request->input('username'));
|
||||
$data['first_name'] = e($request->input('first_name'));
|
||||
$data['last_name'] = e($request->input('last_name'));
|
||||
$data['password'] = e($request->input('password'));
|
||||
|
||||
$user->notify(new WelcomeNotification($data));
|
||||
}
|
||||
|
||||
return Helper::getRedirectOption($request, $user->id, 'Users')
|
||||
->with('success', trans('admin/users/message.success.create'));
|
||||
}
|
||||
@@ -248,20 +229,14 @@ class UsersController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
// Only save groups if the user is a superuser
|
||||
if (auth()->user()->isSuperUser()) {
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
}
|
||||
|
||||
// Update the user fields
|
||||
$user->username = trim($request->input('username'));
|
||||
$user->email = trim($request->input('email'));
|
||||
|
||||
$user->first_name = $request->input('first_name');
|
||||
$user->last_name = $request->input('last_name');
|
||||
$user->two_factor_optin = $request->input('two_factor_optin') ?: 0;
|
||||
$user->locale = $request->input('locale');
|
||||
$user->employee_num = $request->input('employee_num');
|
||||
$user->activated = $request->input('activated', 0);
|
||||
$user->jobtitle = $request->input('jobtitle', null);
|
||||
$user->phone = $request->input('phone');
|
||||
$user->location_id = $request->input('location_id', null);
|
||||
@@ -273,8 +248,6 @@ class UsersController extends Controller
|
||||
$user->city = $request->input('city', null);
|
||||
$user->state = $request->input('state', null);
|
||||
$user->country = $request->input('country', null);
|
||||
// if a user is editing themselves we should always keep activated true
|
||||
$user->activated = $request->input('activated', $request->user()->is($user) ? 1 : 0);
|
||||
$user->zip = $request->input('zip', null);
|
||||
$user->remote = $request->input('remote', 0);
|
||||
$user->vip = $request->input('vip', 0);
|
||||
@@ -283,21 +256,27 @@ class UsersController extends Controller
|
||||
$user->end_date = $request->input('end_date', null);
|
||||
$user->autoassign_licenses = $request->input('autoassign_licenses', 0);
|
||||
|
||||
// Set this here so that we can overwrite it later if the user is an admin or superadmin
|
||||
$user->activated = $request->input('activated', auth()->user()->is($user) ? 1 : $user->activated);
|
||||
|
||||
|
||||
// Update the location of any assets checked out to this user
|
||||
Asset::where('assigned_type', User::class)
|
||||
->where('assigned_to', $user->id)
|
||||
->update(['location_id' => $request->input('location_id', null)]);
|
||||
|
||||
// check for permissions related fields and only set them if the user has permission to edit them
|
||||
if (auth()->user()->can('canEditAuthFields', $user) && auth()->user()->can('editableOnDemo')) {
|
||||
|
||||
$user->username = trim($request->input('username'));
|
||||
$user->email = trim($request->input('email'));
|
||||
$user->activated = $request->input('activated', $request->user()->is($user) ? 1 : 0);
|
||||
|
||||
// Do we want to update the user password?
|
||||
if ($request->filled('password')) {
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
|
||||
// Update the location of any assets checked out to this user
|
||||
Asset::where('assigned_type', User::class)
|
||||
->where('assigned_to', $user->id)
|
||||
->update(['location_id' => $user->location_id]);
|
||||
|
||||
$permissions_array = $request->input('permission');
|
||||
|
||||
// Strip out the superuser permission if the user isn't a superadmin
|
||||
@@ -308,6 +287,19 @@ class UsersController extends Controller
|
||||
|
||||
$user->permissions = json_encode($permissions_array);
|
||||
|
||||
// Only save groups if the user is a superuser
|
||||
if (auth()->user()->isSuperUser()) {
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Update the location of any assets checked out to this user
|
||||
Asset::where('assigned_type', User::class)
|
||||
->where('assigned_to', $user->id)
|
||||
->update(['location_id' => $user->location_id]);
|
||||
|
||||
|
||||
// Handle uploaded avatar
|
||||
app(ImageUploadRequest::class)->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
|
||||
@@ -80,10 +80,21 @@ class UploadFileRequest extends Request
|
||||
{
|
||||
$attributes = [];
|
||||
|
||||
if ($this->file) {
|
||||
if (($this->file) && (is_array($this->file))) {
|
||||
|
||||
for ($i = 0; $i < count($this->file); $i++) {
|
||||
|
||||
try {
|
||||
|
||||
if ($this->file[$i]) {
|
||||
$attributes['file.'.$i] = $this->file[$i]->getClientOriginalName();
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$attributes['file.'.$i] = 'Invalid file';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
|
||||
@@ -80,7 +80,6 @@ class AssetsTransformer
|
||||
'qr' => ($setting->qr_code=='1') ? config('app.url').'/uploads/barcodes/qr-'.str_slug($asset->asset_tag).'-'.str_slug($asset->id).'.png' : null,
|
||||
'alt_barcode' => ($setting->alt_barcode_enabled=='1') ? config('app.url').'/uploads/barcodes/'.str_slug($setting->alt_barcode).'-'.str_slug($asset->asset_tag).'.png' : null,
|
||||
'assigned_to' => $this->transformAssignedTo($asset),
|
||||
'jobtitle' => $asset->assigned ? e($asset->assigned->jobtitle) : null,
|
||||
'warranty_months' => ($asset->warranty_months > 0) ? e($asset->warranty_months.' '.trans('admin/hardware/form.months')) : null,
|
||||
'warranty_expires' => ($asset->warranty_months > 0) ? Helper::getFormattedDateObject($asset->warranty_expires, 'date') : null,
|
||||
'created_by' => ($asset->adminuser) ? [
|
||||
@@ -204,6 +203,7 @@ class AssetsTransformer
|
||||
'last_name'=> ($asset->assigned->last_name) ? e($asset->assigned->last_name) : null,
|
||||
'email'=> ($asset->assigned->email) ? e($asset->assigned->email) : null,
|
||||
'employee_number' => ($asset->assigned->employee_num) ? e($asset->assigned->employee_num) : null,
|
||||
'jobtitle' => $asset->assigned->jobtitle ? e($asset->assigned->jobtitle) : null,
|
||||
'type' => 'user',
|
||||
] : null;
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ abstract class Importer
|
||||
} else {
|
||||
$this->csv = Reader::createFromString($file);
|
||||
}
|
||||
$this->tempPassword = substr(str_shuffle('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'), 0, 40);
|
||||
$this->tempPassword = '*** NO PASSWORD - IMPORTED VIA CSV ***';
|
||||
}
|
||||
|
||||
// Cached Values for import lookups
|
||||
|
||||
@@ -7,7 +7,9 @@ use App\Models\Department;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use App\Notifications\WelcomeNotification;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
|
||||
/**
|
||||
* This is ONLY used for the User Import. When we are importing users
|
||||
@@ -80,6 +82,7 @@ class UserImporter extends ItemImporter
|
||||
$this->item['username'] = $user_formatted_array['username'];
|
||||
}
|
||||
|
||||
|
||||
// Check if a numeric ID was passed. If it does, use that above all else.
|
||||
if ((array_key_exists('id', $this->item) && ($this->item['id'] != "") && (is_numeric($this->item['id'])))) {
|
||||
$user = User::find($this->item['id']);
|
||||
@@ -89,12 +92,25 @@ class UserImporter extends ItemImporter
|
||||
|
||||
if ($user) {
|
||||
|
||||
// If the user does not want to update existing values, only add new ones, bail out
|
||||
if (! $this->updating) {
|
||||
Log::debug('A matching User '.$this->item['name'].' already exists. ');
|
||||
return;
|
||||
}
|
||||
|
||||
$this->log('Updating User');
|
||||
|
||||
// Todo - check that this works
|
||||
if (!Gate::allows('canEditAuthFields', $user)) {
|
||||
unset($user->username);
|
||||
unset($user->email);
|
||||
unset($user->password);
|
||||
unset($user->activated);
|
||||
}
|
||||
|
||||
$user->update($this->sanitizeItemForUpdating($user));
|
||||
|
||||
// Why do we have to do this twice? Update should
|
||||
$user->save();
|
||||
|
||||
// Update the location of any assets checked out to this user
|
||||
@@ -110,28 +126,32 @@ class UserImporter extends ItemImporter
|
||||
|
||||
// This needs to be applied after the update logic, otherwise we'll overwrite user passwords
|
||||
// Issue #5408
|
||||
$this->item['password'] = bcrypt($this->tempPassword);
|
||||
$this->item['password'] = $this->tempPassword;
|
||||
|
||||
$this->log('No matching user, creating one');
|
||||
$user = new User();
|
||||
$user->created_by = auth()->id();
|
||||
|
||||
$user->fill($this->sanitizeItemForStoring($user));
|
||||
|
||||
// TODO - check for gate here I guess
|
||||
|
||||
|
||||
if ($user->save()) {
|
||||
$this->log('User '.$this->item['name'].' was created');
|
||||
|
||||
if (($user->email) && ($user->activated == '1')) {
|
||||
$data = [
|
||||
'email' => $user->email,
|
||||
'username' => $user->username,
|
||||
'first_name' => $user->first_name,
|
||||
'last_name' => $user->last_name,
|
||||
'password' => $this->tempPassword,
|
||||
];
|
||||
|
||||
if ($this->send_welcome) {
|
||||
$user->notify(new WelcomeNotification($data));
|
||||
|
||||
try {
|
||||
$user->notify(new WelcomeNotification($user));
|
||||
} catch (\Exception $e) {
|
||||
Log::warning('Could not send welcome notification for user: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
$user = null;
|
||||
$this->item = null;
|
||||
@@ -140,9 +160,9 @@ class UserImporter extends ItemImporter
|
||||
}
|
||||
|
||||
$this->logError($user, 'User');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch an existing department, or create new if it doesn't exist
|
||||
*
|
||||
|
||||
@@ -4,10 +4,12 @@ namespace App\Listeners;
|
||||
|
||||
use App\Events\CheckoutableCheckedOut;
|
||||
use App\Mail\CheckinAccessoryMail;
|
||||
use App\Mail\CheckinComponentMail;
|
||||
use App\Mail\CheckinLicenseMail;
|
||||
use App\Mail\CheckoutAccessoryMail;
|
||||
use App\Mail\CheckoutAssetMail;
|
||||
use App\Mail\CheckinAssetMail;
|
||||
use App\Mail\CheckoutComponentMail;
|
||||
use App\Mail\CheckoutConsumableMail;
|
||||
use App\Mail\CheckoutLicenseMail;
|
||||
use App\Models\Accessory;
|
||||
@@ -22,9 +24,11 @@ use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CheckinAccessoryNotification;
|
||||
use App\Notifications\CheckinAssetNotification;
|
||||
use App\Notifications\CheckinComponentNotification;
|
||||
use App\Notifications\CheckinLicenseSeatNotification;
|
||||
use App\Notifications\CheckoutAccessoryNotification;
|
||||
use App\Notifications\CheckoutAssetNotification;
|
||||
use App\Notifications\CheckoutComponentNotification;
|
||||
use App\Notifications\CheckoutConsumableNotification;
|
||||
use App\Notifications\CheckoutLicenseSeatNotification;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
@@ -39,7 +43,7 @@ use Osama\LaravelTeamsNotification\TeamsNotification;
|
||||
class CheckoutableListener
|
||||
{
|
||||
private array $skipNotificationsFor = [
|
||||
Component::class,
|
||||
// Component::class,
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -145,7 +149,6 @@ class CheckoutableListener
|
||||
$shouldSendEmailToUser = $this->checkoutableCategoryShouldSendEmail($event->checkoutable);
|
||||
$shouldSendEmailToAlertAddress = $this->shouldSendEmailToAlertAddress();
|
||||
$shouldSendWebhookNotification = $this->shouldSendWebhookNotification();
|
||||
|
||||
if (!$shouldSendEmailToUser && !$shouldSendEmailToAlertAddress && !$shouldSendWebhookNotification) {
|
||||
return;
|
||||
}
|
||||
@@ -269,6 +272,9 @@ class CheckoutableListener
|
||||
case LicenseSeat::class:
|
||||
$notificationClass = CheckinLicenseSeatNotification::class;
|
||||
break;
|
||||
case Component::class:
|
||||
$notificationClass = CheckinComponentNotification::class;
|
||||
break;
|
||||
}
|
||||
|
||||
Log::debug('Notification class: '.$notificationClass);
|
||||
@@ -299,6 +305,9 @@ class CheckoutableListener
|
||||
case LicenseSeat::class:
|
||||
$notificationClass = CheckoutLicenseSeatNotification::class;
|
||||
break;
|
||||
case Component::class:
|
||||
$notificationClass = CheckoutComponentNotification::class;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -310,6 +319,7 @@ class CheckoutableListener
|
||||
Asset::class => CheckoutAssetMail::class,
|
||||
LicenseSeat::class => CheckoutLicenseMail::class,
|
||||
Consumable::class => CheckoutConsumableMail::class,
|
||||
Component::class => CheckoutComponentMail::class,
|
||||
];
|
||||
$mailable= $lookup[get_class($event->checkoutable)];
|
||||
|
||||
@@ -322,8 +332,8 @@ class CheckoutableListener
|
||||
Accessory::class => CheckinAccessoryMail::class,
|
||||
Asset::class => CheckinAssetMail::class,
|
||||
LicenseSeat::class => CheckinLicenseMail::class,
|
||||
Component::class => CheckinComponentMail::class,
|
||||
];
|
||||
|
||||
$mailable= $lookup[get_class($event->checkoutable)];
|
||||
|
||||
return new $mailable($event->checkoutable, $event->checkedOutTo, $event->checkedInBy, $event->note);
|
||||
@@ -469,7 +479,8 @@ class CheckoutableListener
|
||||
return match (true) {
|
||||
$checkoutable instanceof Asset => $checkoutable->model->category,
|
||||
$checkoutable instanceof Accessory,
|
||||
$checkoutable instanceof Consumable => $checkoutable->category,
|
||||
$checkoutable instanceof Consumable,
|
||||
$checkoutable instanceof Component => $checkoutable->category,
|
||||
$checkoutable instanceof LicenseSeat => $checkoutable->license->category,
|
||||
};
|
||||
}
|
||||
|
||||
71
app/Mail/CheckinComponentMail.php
Normal file
71
app/Mail/CheckinComponentMail.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Component;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Address;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class CheckinComponentMail extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*/
|
||||
public function __construct(Component $component, $checkedOutTo, User $checkedInby, $note)
|
||||
{
|
||||
$this->item = $component;
|
||||
$this->target = $checkedOutTo;
|
||||
$this->admin = $checkedInby;
|
||||
$this->note = $note;
|
||||
$this->settings = Setting::getSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*/
|
||||
public function envelope(): Envelope
|
||||
{
|
||||
$from = new Address(config('mail.from.address'), config('mail.from.name'));
|
||||
|
||||
return new Envelope(
|
||||
from: $from,
|
||||
subject: trans('mail.Confirm_component_checkin'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*/
|
||||
public function content(): Content
|
||||
{
|
||||
return new Content(
|
||||
markdown: 'mail.markdown.checkin-component',
|
||||
with: [
|
||||
'item' => $this->item,
|
||||
'admin' => $this->admin,
|
||||
'note' => $this->note,
|
||||
'target' => $this->target,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attachments for the message.
|
||||
*
|
||||
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
|
||||
*/
|
||||
public function attachments(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
82
app/Mail/CheckoutComponentMail.php
Normal file
82
app/Mail/CheckoutComponentMail.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Models\Component;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Address;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class CheckoutComponentMail extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*/
|
||||
public function __construct(Component $component, $checkedOutTo, User $checkedOutBy, $acceptance, $note)
|
||||
{
|
||||
$this->item = $component;
|
||||
$this->admin = $checkedOutBy;
|
||||
$this->note = $note;
|
||||
$this->target = $checkedOutTo;
|
||||
$this->acceptance = $acceptance;
|
||||
$this->qty = $component->assets->first()?->pivot?->assigned_qty;
|
||||
|
||||
$this->settings = Setting::getSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*/
|
||||
public function envelope(): Envelope
|
||||
{
|
||||
$from = new Address(config('mail.from.address'), config('mail.from.name'));
|
||||
|
||||
return new Envelope(
|
||||
from: $from,
|
||||
subject: trans('mail.Confirm_component_delivery'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*/
|
||||
public function content(): Content
|
||||
{
|
||||
|
||||
$eula = $this->item->getEula();
|
||||
$req_accept = $this->item->requireAcceptance();
|
||||
|
||||
$accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance);
|
||||
|
||||
return new Content(
|
||||
markdown: 'mail.markdown.checkout-component',
|
||||
with: [
|
||||
'item' => $this->item,
|
||||
'admin' => $this->admin,
|
||||
'note' => $this->note,
|
||||
'target' => $this->target,
|
||||
'eula' => $eula,
|
||||
'req_accept' => $req_accept,
|
||||
'accept_url' => $accept_url,
|
||||
'qty' => $this->qty,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attachments for the message.
|
||||
*
|
||||
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
|
||||
*/
|
||||
public function attachments(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -74,6 +74,8 @@ class Actionlog extends SnipeModel
|
||||
'assets' => ['asset_tag','name', 'serial', 'order_number', 'notes', 'purchase_date'],
|
||||
'assets.model' => ['name', 'model_number', 'eol', 'notes'],
|
||||
'assets.model.category' => ['name', 'notes'],
|
||||
'assets.location' => ['name'],
|
||||
'assets.defaultLoc' => ['name'],
|
||||
'assets.model.manufacturer' => ['name', 'notes'],
|
||||
'licenses' => ['name', 'serial', 'notes', 'order_number', 'license_email', 'license_name', 'purchase_order', 'purchase_date'],
|
||||
'licenses.category' => ['name', 'notes'],
|
||||
|
||||
@@ -15,6 +15,8 @@ use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
@@ -421,14 +423,36 @@ class Asset extends Depreciable
|
||||
{
|
||||
// Check to see if any of the custom fields were included on the form and if they have any values
|
||||
if (($this->model) && ($this->model->fieldset) && ($this->model->fieldset->fields)) {
|
||||
|
||||
foreach ($this->model->fieldset->fields as $field) {
|
||||
|
||||
if (($field->{$checkin_checkout} == 1) && (request()->has($field->db_column))) {
|
||||
$this->{$field->db_column} = request()->get($field->db_column);
|
||||
|
||||
if ($field->field_encrypted == '1') {
|
||||
|
||||
if (Gate::allows('assets.view.encrypted_custom_fields')) {
|
||||
if (is_array(request()->input($field->db_column))) {
|
||||
$this->{$field->db_column} = Crypt::encrypt(implode(', ', request()->input($field->db_column)));
|
||||
} else {
|
||||
$this->{$field->db_column} = Crypt::encrypt(request()->get($field->db_column));
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (is_array(request()->input($field->db_column))) {
|
||||
$this->{$field->db_column} = implode(', ', request()->input($field->db_column));
|
||||
} else {
|
||||
$this->{$field->db_column} = request()->input($field->db_column);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Establishes the asset -> depreciation relationship
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Traits\HasUploads;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
/**
|
||||
@@ -203,6 +205,36 @@ class Component extends SnipeModel
|
||||
{
|
||||
return $this->belongsTo(\App\Models\Manufacturer::class, 'manufacturer_id');
|
||||
}
|
||||
/**
|
||||
* Determine whether this asset requires acceptance by the assigned user
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
* @return bool
|
||||
*/
|
||||
public function requireAcceptance()
|
||||
{
|
||||
return $this->category->require_acceptance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for a category-specific EULA, and if that doesn't exist,
|
||||
* checks for a settings level EULA
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
* @return string | false
|
||||
*/
|
||||
public function getEula()
|
||||
{
|
||||
if ($this->category->eula_text) {
|
||||
return Helper::parseEscapedMarkedown($this->category->eula_text);
|
||||
} elseif ((Setting::getSettings()->default_eula_text) && ($this->category->use_default_eula == '1')) {
|
||||
return Helper::parseEscapedMarkedown(Setting::getSettings()->default_eula_text);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the component -> action logs relationship
|
||||
@@ -248,6 +280,19 @@ class Component extends SnipeModel
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether to send a checkin/checkout email based on
|
||||
* asset model category
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
* @return bool
|
||||
*/
|
||||
public function checkin_email()
|
||||
{
|
||||
return $this->category?->checkin_email;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check how many items within a component are remaining
|
||||
|
||||
@@ -23,6 +23,7 @@ use Illuminate\Support\Str;
|
||||
use Laravel\Passport\HasApiTokens;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use App\Presenters\UserPresenter;
|
||||
|
||||
class User extends SnipeModel implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, HasLocalePreference
|
||||
{
|
||||
@@ -30,7 +31,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
use CompanyableTrait;
|
||||
use HasUploads;
|
||||
|
||||
protected $presenter = \App\Presenters\UserPresenter::class;
|
||||
protected $presenter = UserPresenter::class;
|
||||
use SoftDeletes, ValidatingTrait, Loggable;
|
||||
use Authenticatable, Authorizable, CanResetPassword, HasApiTokens;
|
||||
use UniqueUndeletedTrait;
|
||||
@@ -38,7 +39,16 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
use Presentable;
|
||||
use Searchable;
|
||||
|
||||
protected $hidden = ['password', 'remember_token', 'permissions', 'reset_password_code', 'persist_code'];
|
||||
protected $hidden = [
|
||||
'password',
|
||||
'remember_token',
|
||||
'permissions',
|
||||
'reset_password_code',
|
||||
'persist_code',
|
||||
'two_factor_secret',
|
||||
'activation_code',
|
||||
];
|
||||
|
||||
protected $table = 'users';
|
||||
protected $injectUniqueIdentifier = true;
|
||||
|
||||
@@ -193,11 +203,19 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
{
|
||||
$user_groups = $this->groups;
|
||||
if (($this->permissions == '') && (count($user_groups) == 0)) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$user_permissions = $this->permissions;
|
||||
|
||||
if (is_object($this->permissions)) {
|
||||
$user_permissions = json_decode(json_encode($this->permissions), true);
|
||||
}
|
||||
|
||||
if (is_string($this->permissions)) {
|
||||
$user_permissions = json_decode($this->permissions, true);
|
||||
}
|
||||
|
||||
|
||||
$is_user_section_permissions_set = ($user_permissions != '') && array_key_exists($section, $user_permissions);
|
||||
//If the user is explicitly granted, return true
|
||||
@@ -251,6 +269,18 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
return $this->checkPermissionSection('superuser');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the user is an admin
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v8.1.18]
|
||||
* @return bool
|
||||
*/
|
||||
public function isAdmin()
|
||||
{
|
||||
return $this->checkPermissionSection('admin');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the user can edit their own profile
|
||||
@@ -278,13 +308,15 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
*/
|
||||
public function isDeletable()
|
||||
{
|
||||
|
||||
return Gate::allows('delete', $this)
|
||||
&& ($this->assets->count() === 0)
|
||||
&& ($this->licenses->count() === 0)
|
||||
&& ($this->consumables->count() === 0)
|
||||
&& ($this->accessories->count() === 0)
|
||||
&& ($this->managedLocations->count() === 0)
|
||||
&& ($this->managesUsers->count() === 0)
|
||||
&& (($this->assets_count ?? $this->assets()->count()) === 0)
|
||||
&& (($this->accessories_count ?? $this->accessories()->count()) === 0)
|
||||
&& (($this->licenses_count ?? $this->licenses()->count()) === 0)
|
||||
&& (($this->consumables_count ?? $this->consumables()->count()) === 0)
|
||||
&& (($this->accessories_count ?? $this->accessories()->count()) === 0)
|
||||
&& (($this->manages_users_count ?? $this->managesUsers()->count()) === 0)
|
||||
&& (($this->manages_locations_count ?? $this->managedLocations()->count()) === 0)
|
||||
&& ($this->deleted_at == '');
|
||||
}
|
||||
|
||||
|
||||
165
app/Notifications/CheckinComponentNotification.php
Normal file
165
app/Notifications/CheckinComponentNotification.php
Normal file
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use App\Models\Component;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Channels\SlackWebhookChannel;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Support\Str;
|
||||
use NotificationChannels\GoogleChat\Card;
|
||||
use NotificationChannels\GoogleChat\GoogleChatChannel;
|
||||
use NotificationChannels\GoogleChat\GoogleChatMessage;
|
||||
use NotificationChannels\GoogleChat\Section;
|
||||
use NotificationChannels\GoogleChat\Widgets\KeyValue;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsChannel;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage;
|
||||
|
||||
class CheckinComponentNotification extends Notification
|
||||
{
|
||||
use Queueable;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
private $params;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @param $params
|
||||
*/
|
||||
public function __construct(Component $component, $checkedOutTo, User $checkedInBy, $note)
|
||||
{
|
||||
$this->target = $checkedOutTo;
|
||||
$this->item = $component;
|
||||
$this->admin = $checkedInBy;
|
||||
$this->note = $note;
|
||||
$this->settings = Setting::getSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function via()
|
||||
{
|
||||
$notifyBy = [];
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'google' && Setting::getSettings()->webhook_endpoint) {
|
||||
|
||||
$notifyBy[] = GoogleChatChannel::class;
|
||||
}
|
||||
if (Setting::getSettings()->webhook_selected == 'microsoft' && Setting::getSettings()->webhook_endpoint) {
|
||||
|
||||
$notifyBy[] = MicrosoftTeamsChannel::class;
|
||||
}
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'slack' || Setting::getSettings()->webhook_selected == 'general' ) {
|
||||
$notifyBy[] = SlackWebhookChannel::class;
|
||||
}
|
||||
|
||||
return $notifyBy;
|
||||
}
|
||||
|
||||
public function toSlack()
|
||||
{
|
||||
$target = $this->target;
|
||||
$admin = $this->admin;
|
||||
$item = $this->item;
|
||||
$note = $this->note;
|
||||
$botname = ($this->settings->webhook_botname) ? $this->settings->webhook_botname : 'Snipe-Bot';
|
||||
$channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : '';
|
||||
|
||||
if ($admin) {
|
||||
$fields = [
|
||||
trans('general.from') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
|
||||
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
|
||||
];
|
||||
|
||||
if ($item->location) {
|
||||
$fields[trans('general.location')] = $item->location->name;
|
||||
}
|
||||
|
||||
if ($item->company) {
|
||||
$fields[trans('general.company')] = $item->company->name;
|
||||
}
|
||||
|
||||
} else {
|
||||
$fields = [
|
||||
'To' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
|
||||
'By' => 'CLI tool',
|
||||
];
|
||||
}
|
||||
|
||||
return (new SlackMessage)
|
||||
->content(':arrow_down: :package: '.trans('mail.Component_checkin_notification'))
|
||||
->from($botname)
|
||||
->to($channel)
|
||||
->attachment(function ($attachment) use ($item, $note, $admin, $fields) {
|
||||
$attachment->title(htmlspecialchars_decode($item->present()->name), $item->present()->viewUrl())
|
||||
->fields($fields)
|
||||
->content($note);
|
||||
});
|
||||
}
|
||||
public function toMicrosoftTeams()
|
||||
{
|
||||
$target = $this->target;
|
||||
$admin = $this->admin;
|
||||
$item = $this->item;
|
||||
$note = $this->note;
|
||||
if(!Str::contains(Setting::getSettings()->webhook_endpoint, 'workflows')) {
|
||||
return MicrosoftTeamsMessage::create()
|
||||
->to($this->settings->webhook_endpoint)
|
||||
->type('success')
|
||||
->addStartGroupToSection('activityTitle')
|
||||
->title(trans('mail.Component_checkin_notification'))
|
||||
->addStartGroupToSection('activityText')
|
||||
->fact(htmlspecialchars_decode($item->present()->name), '', 'header')
|
||||
->fact(trans('mail.Component_checkin_notification')." by ", $admin->present()->fullName() ?: 'CLI tool')
|
||||
->fact(trans('mail.checkedin_from'), $target->present()->fullName())
|
||||
->fact(trans('admin/consumables/general.remaining'), $item->numRemaining())
|
||||
->fact(trans('mail.notes'), $note ?: '');
|
||||
}
|
||||
|
||||
$message = trans('mail.Component_checkin_notification');
|
||||
$details = [
|
||||
trans('mail.checkedin_from')=> $target->present()->fullName(),
|
||||
trans('mail.Component_checkin_notification')." by " => $admin->present()->fullName() ?: 'CLI tool',
|
||||
trans('admin/consumables/general.remaining') => $item->numRemaining(),
|
||||
trans('mail.notes') => $note ?: '',
|
||||
];
|
||||
|
||||
return array($message, $details);
|
||||
}
|
||||
public function toGoogleChat()
|
||||
{
|
||||
$target = $this->target;
|
||||
$item = $this->item;
|
||||
$note = $this->note;
|
||||
|
||||
return GoogleChatMessage::create()
|
||||
->to($this->settings->webhook_endpoint)
|
||||
->card(
|
||||
Card::create()
|
||||
->header(
|
||||
'<strong>'.trans('mail.Component_checkin_notification').'</strong>' ?: '',
|
||||
htmlspecialchars_decode($item->present()->name) ?: '',
|
||||
)
|
||||
->section(
|
||||
Section::create(
|
||||
KeyValue::create(
|
||||
trans('mail.checkedin_from') ?: '',
|
||||
$target->present()->fullName() ?: '',
|
||||
trans('admin/consumables/general.remaining').': '.$item->numRemaining(),
|
||||
)
|
||||
->onClick(route('components.show', $item->id))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
164
app/Notifications/CheckoutComponentNotification.php
Normal file
164
app/Notifications/CheckoutComponentNotification.php
Normal file
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use App\Models\Component;
|
||||
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Channels\SlackWebhookChannel;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Support\Str;
|
||||
use NotificationChannels\GoogleChat\Card;
|
||||
use NotificationChannels\GoogleChat\GoogleChatChannel;
|
||||
use NotificationChannels\GoogleChat\GoogleChatMessage;
|
||||
use NotificationChannels\GoogleChat\Section;
|
||||
use NotificationChannels\GoogleChat\Widgets\KeyValue;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsChannel;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage;
|
||||
|
||||
|
||||
class CheckoutComponentNotification extends Notification
|
||||
{
|
||||
use Queueable;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
private $params;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @param $params
|
||||
*/
|
||||
public function __construct(Component $component, $checkedOutTo, User $checkedOutBy, $acceptance, $note)
|
||||
{
|
||||
$this->item = $component;
|
||||
$this->admin = $checkedOutBy;
|
||||
$this->note = $note;
|
||||
$this->target = $checkedOutTo;
|
||||
$this->acceptance = $acceptance;
|
||||
$this->qty = $component->checkout_qty;
|
||||
|
||||
$this->settings = Setting::getSettings();
|
||||
}
|
||||
|
||||
/**`
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function via()
|
||||
{
|
||||
$notifyBy = [];
|
||||
if (Setting::getSettings()->webhook_selected == 'google' && Setting::getSettings()->webhook_endpoint) {
|
||||
|
||||
$notifyBy[] = GoogleChatChannel::class;
|
||||
}
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'microsoft' && Setting::getSettings()->webhook_endpoint) {
|
||||
|
||||
$notifyBy[] = MicrosoftTeamsChannel::class;
|
||||
}
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'slack' || Setting::getSettings()->webhook_selected == 'general' ) {
|
||||
$notifyBy[] = SlackWebhookChannel::class;
|
||||
}
|
||||
|
||||
return $notifyBy;
|
||||
}
|
||||
|
||||
public function toSlack()
|
||||
{
|
||||
$target = $this->target;
|
||||
$admin = $this->admin;
|
||||
$item = $this->item;
|
||||
$note = $this->note;
|
||||
$botname = ($this->settings->webhook_botname) ? $this->settings->webhook_botname : 'Snipe-Bot';
|
||||
$channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : '';
|
||||
|
||||
$fields = [
|
||||
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
|
||||
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
|
||||
];
|
||||
|
||||
if ($item->location) {
|
||||
$fields[trans('general.location')] = $item->location->name;
|
||||
}
|
||||
|
||||
if ($item->company) {
|
||||
$fields[trans('general.company')] = $item->company->name;
|
||||
}
|
||||
|
||||
return (new SlackMessage)
|
||||
->content(':arrow_up: :package: '.trans('mail.Component_checkout_notification'))
|
||||
->from($botname)
|
||||
->to($channel)
|
||||
->attachment(function ($attachment) use ($item, $note, $admin, $fields) {
|
||||
$attachment->title(htmlspecialchars_decode($item->present()->name), $item->present()->viewUrl())
|
||||
->fields($fields)
|
||||
->content($note);
|
||||
});
|
||||
}
|
||||
public function toMicrosoftTeams()
|
||||
{
|
||||
$target = $this->target;
|
||||
$admin = $this->admin;
|
||||
$item = $this->item;
|
||||
$note = $this->note;
|
||||
|
||||
if(!Str::contains(Setting::getSettings()->webhook_endpoint, 'workflows')) {
|
||||
return MicrosoftTeamsMessage::create()
|
||||
->to($this->settings->webhook_endpoint)
|
||||
->type('success')
|
||||
->addStartGroupToSection('activityTitle')
|
||||
->title(trans('mail.Component_checkout_notification'))
|
||||
->addStartGroupToSection('activityText')
|
||||
->fact(htmlspecialchars_decode($item->present()->name), '', 'activityTitle')
|
||||
->fact(trans('mail.Component_checkout_notification')." by ", $admin->present()->fullName())
|
||||
->fact(trans('mail.assigned_to'), $target->present()->fullName())
|
||||
->fact(trans('admin/consumables/general.remaining'), $item->numRemaining())
|
||||
->fact(trans('mail.notes'), $note ?: '');
|
||||
}
|
||||
|
||||
$message = trans('mail.Component_checkout_notification');
|
||||
$details = [
|
||||
trans('mail.assigned_to') => $target->present()->fullName(),
|
||||
trans('mail.item') => htmlspecialchars_decode($item->present()->name),
|
||||
trans('mail.Component_checkout_notification').' by' => $admin->present()->fullName(),
|
||||
trans('admin/consumables/general.remaining') => $item->numRemaining(),
|
||||
trans('mail.notes') => $note ?: '',
|
||||
];
|
||||
|
||||
return array($message, $details);
|
||||
}
|
||||
public function toGoogleChat()
|
||||
{
|
||||
$target = $this->target;
|
||||
$item = $this->item;
|
||||
$note = $this->note;
|
||||
|
||||
return GoogleChatMessage::create()
|
||||
->to($this->settings->webhook_endpoint)
|
||||
->card(
|
||||
Card::create()
|
||||
->header(
|
||||
'<strong>'.trans('mail.Component_checkout_notification').'</strong>' ?: '',
|
||||
htmlspecialchars_decode($item->present()->name) ?: '',
|
||||
)
|
||||
->section(
|
||||
Section::create(
|
||||
KeyValue::create(
|
||||
trans('mail.assigned_to') ?: '',
|
||||
$target->present()->fullName() ?: '',
|
||||
trans('admin/consumables/general.remaining').': '.$item->numRemaining(),
|
||||
)
|
||||
->onClick(route('api.assets.show', $target->id))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -5,26 +5,23 @@ namespace App\Notifications;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use App\Models\User;
|
||||
|
||||
class WelcomeNotification extends Notification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
private $_data = [];
|
||||
|
||||
public $expire_date;
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $content)
|
||||
public function __construct(public User $user)
|
||||
{
|
||||
$this->_data['email'] = htmlspecialchars_decode($content['email']);
|
||||
$this->_data['first_name'] = htmlspecialchars_decode($content['first_name']);
|
||||
$this->_data['last_name'] = htmlspecialchars_decode($content['last_name']);
|
||||
$this->_data['username'] = htmlspecialchars_decode($content['username']);
|
||||
$this->_data['password'] = htmlspecialchars_decode($content['password']);
|
||||
$this->_data['url'] = config('app.url');
|
||||
$this->user->token = Password::broker('invites')->createToken($user);
|
||||
$this->user->expire_date = now()->addMinutes((int) config('auth.passwords.invites.expire', 2880))->format('F j, Y, g:i a');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,8 +41,9 @@ class WelcomeNotification extends Notification
|
||||
*/
|
||||
public function toMail()
|
||||
{
|
||||
|
||||
return (new MailMessage())
|
||||
->subject(trans('mail.welcome', ['name' => $this->_data['first_name'].' '.$this->_data['last_name']]))
|
||||
->markdown('notifications.Welcome', $this->_data);
|
||||
->subject(trans('mail.welcome', ['name' => $this->user->first_name.' '.$this->user->last_name]))
|
||||
->markdown('notifications.Welcome', $this->user->toArray());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,6 +115,7 @@ class AssetPresenter extends Presenter
|
||||
'sortable' => true,
|
||||
'title' => trans('admin/users/table.title'),
|
||||
'visible' => false,
|
||||
'formatter' => 'jobtitleFormatter',
|
||||
], [
|
||||
'field' => 'location',
|
||||
'searchable' => true,
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace App\Presenters;
|
||||
/**
|
||||
* Class AccessoryPresenter
|
||||
*/
|
||||
class UploadsPresenter extends Presenter
|
||||
class UploadedFilesPresenter extends Presenter
|
||||
{
|
||||
/**
|
||||
* Json Column Layout for bootstrap table
|
||||
|
||||
@@ -101,13 +101,21 @@ class AuthServiceProvider extends ServiceProvider
|
||||
* This is where we set the superadmin permission to allow superadmins to be able to do everything within the system.
|
||||
*
|
||||
*/
|
||||
Gate::before(function ($user) {
|
||||
Gate::before(function ($user, $ability) {
|
||||
|
||||
// Disallow even superadmins to edit non-editable things when in demo mode.
|
||||
// (We have to do this to prevent jerks from trying to break the demo by editing things they shouldn't.)
|
||||
if (($ability == 'editableOnDemo') && (config('app.lock_passwords'))) {
|
||||
return false;
|
||||
}
|
||||
if ($user->isSuperUser()) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* GENERAL GATES
|
||||
*
|
||||
@@ -115,6 +123,45 @@ class AuthServiceProvider extends ServiceProvider
|
||||
* use in our controllers to determine if a user has access to a certain area.
|
||||
*/
|
||||
|
||||
Gate::define('canEditAuthFields', function ($user, $item) {
|
||||
|
||||
if ($item instanceof User) {
|
||||
|
||||
// if they can only edit users, deny them if the user is admin or superadmin
|
||||
if (($user->hasAccess('users.edit')) && (!$user->isAdmin()) && (!$user->isAdmin())) {
|
||||
|
||||
if ($item->isAdmin() || $item->isSuperUser()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// if they are an admin, deny them only if the user is a superadmin
|
||||
if ($user->hasAccess('admin')) {
|
||||
if ($item->isSuperUser()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Define the demo mode gate so we have an easy way to use @can and Gate::allows()
|
||||
*/
|
||||
Gate::define('editableOnDemo', function () {
|
||||
if (config('app.lock_passwords')) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
Gate::define('admin', function ($user) {
|
||||
if ($user->hasAccess('admin')) {
|
||||
return true;
|
||||
@@ -249,5 +296,6 @@ class AuthServiceProvider extends ServiceProvider
|
||||
return $user->canEditProfile();
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
28
composer.lock
generated
28
composer.lock
generated
@@ -4532,23 +4532,23 @@
|
||||
},
|
||||
{
|
||||
"name": "livewire/livewire",
|
||||
"version": "v3.5.18",
|
||||
"version": "v3.6.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/livewire/livewire.git",
|
||||
"reference": "62f0fa6b340a467c25baa590a567d9a134b357da"
|
||||
"reference": "ef04be759da41b14d2d129e670533180a44987dc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/livewire/livewire/zipball/62f0fa6b340a467c25baa590a567d9a134b357da",
|
||||
"reference": "62f0fa6b340a467c25baa590a567d9a134b357da",
|
||||
"url": "https://api.github.com/repos/livewire/livewire/zipball/ef04be759da41b14d2d129e670533180a44987dc",
|
||||
"reference": "ef04be759da41b14d2d129e670533180a44987dc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/database": "^10.0|^11.0",
|
||||
"illuminate/routing": "^10.0|^11.0",
|
||||
"illuminate/support": "^10.0|^11.0",
|
||||
"illuminate/validation": "^10.0|^11.0",
|
||||
"illuminate/database": "^10.0|^11.0|^12.0",
|
||||
"illuminate/routing": "^10.0|^11.0|^12.0",
|
||||
"illuminate/support": "^10.0|^11.0|^12.0",
|
||||
"illuminate/validation": "^10.0|^11.0|^12.0",
|
||||
"laravel/prompts": "^0.1.24|^0.2|^0.3",
|
||||
"league/mime-type-detection": "^1.9",
|
||||
"php": "^8.1",
|
||||
@@ -4557,11 +4557,11 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"calebporzio/sushi": "^2.1",
|
||||
"laravel/framework": "^10.15.0|^11.0",
|
||||
"laravel/framework": "^10.15.0|^11.0|^12.0",
|
||||
"mockery/mockery": "^1.3.1",
|
||||
"orchestra/testbench": "^8.21.0|^9.0",
|
||||
"orchestra/testbench-dusk": "^8.24|^9.1",
|
||||
"phpunit/phpunit": "^10.4",
|
||||
"orchestra/testbench": "^8.21.0|^9.0|^10.0",
|
||||
"orchestra/testbench-dusk": "^8.24|^9.1|^10.0",
|
||||
"phpunit/phpunit": "^10.4|^11.5",
|
||||
"psy/psysh": "^0.11.22|^0.12"
|
||||
},
|
||||
"type": "library",
|
||||
@@ -4596,7 +4596,7 @@
|
||||
"description": "A front-end framework for Laravel.",
|
||||
"support": {
|
||||
"issues": "https://github.com/livewire/livewire/issues",
|
||||
"source": "https://github.com/livewire/livewire/tree/v3.5.18"
|
||||
"source": "https://github.com/livewire/livewire/tree/v3.6.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4604,7 +4604,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-12-23T15:05:02+00:00"
|
||||
"time": "2025-07-17T05:12:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "masterminds/html5",
|
||||
|
||||
@@ -104,6 +104,16 @@ return [
|
||||
]
|
||||
|
||||
],
|
||||
|
||||
'invites' => [
|
||||
'provider' => 'users',
|
||||
'table' => 'password_resets',
|
||||
'expire' => env('INVITE_PASSWORD_LINK_EXPIRES', 2880),
|
||||
'throttle' => [
|
||||
'max_attempts' => env('LOGIN_MAX_ATTEMPTS', 5),
|
||||
'lockout_duration' => env('LOGIN_LOCKOUT_DURATION', 60),
|
||||
]
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
return array (
|
||||
'app_version' => 'v8.1.18',
|
||||
'full_app_version' => 'v8.1.18 - build 18876-g4c6249eb9',
|
||||
'build_version' => '18876',
|
||||
'app_version' => 'v8.2.1',
|
||||
'full_app_version' => 'v8.2.1 - build 19068-g6ca49a20c',
|
||||
'build_version' => '19068',
|
||||
'prerelease_version' => '',
|
||||
'hash_version' => 'g4c6249eb9',
|
||||
'full_hash' => 'v8.1.18-77-g4c6249eb9',
|
||||
'hash_version' => 'g6ca49a20c',
|
||||
'full_hash' => 'v8.2.1-10-g6ca49a20c',
|
||||
'branch' => 'develop',
|
||||
);
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
//
|
||||
Artisan::call("snipeit:clean-checkout-acceptances");
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
};
|
||||
@@ -51,8 +51,6 @@ class AssetModelSeeder extends Seeder
|
||||
$del_files = Storage::files($dst);
|
||||
|
||||
foreach ($del_files as $del_file) { // iterate files
|
||||
$file_to_delete = str_replace($src, '', $del_file);
|
||||
Log::debug('Deleting: '.$file_to_delete);
|
||||
try {
|
||||
Storage::disk('public')->delete($dst.$del_file);
|
||||
} catch (\Exception $e) {
|
||||
@@ -63,7 +61,6 @@ class AssetModelSeeder extends Seeder
|
||||
$add_files = glob($src.'/*.*');
|
||||
foreach ($add_files as $add_file) {
|
||||
$file_to_copy = str_replace($src, '', $add_file);
|
||||
Log::debug('Copying: '.$file_to_copy);
|
||||
try {
|
||||
Storage::disk('public')->put($dst.$file_to_copy, file_get_contents($src.$file_to_copy));
|
||||
} catch (\Exception $e) {
|
||||
|
||||
1939
package-lock.json
generated
1939
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
13
package.json
13
package.json
@@ -18,11 +18,11 @@
|
||||
"devDependencies": {
|
||||
"all-contributors-cli": "^6.26.1",
|
||||
"axios": "^1.7.2",
|
||||
"babel-preset-latest": "^6.24.1",
|
||||
"jquery": "<3.6.0",
|
||||
"laravel-mix": "^6.0.49",
|
||||
"lodash": "^4.17.20",
|
||||
"postcss": "^8.4.5"
|
||||
"postcss": "^8.4.5",
|
||||
"webpack": "^5.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^6.7.2",
|
||||
@@ -37,7 +37,7 @@
|
||||
"bootstrap-less": "^3.3.8",
|
||||
"bootstrap-table": "1.24.1",
|
||||
"canvas-confetti": "^1.9.3",
|
||||
"chart.js": "^2.9.4",
|
||||
"chart.js": "4.5.0",
|
||||
"clipboard": "^2.0.11",
|
||||
"css-loader": "^5.0.0",
|
||||
"ekko-lightbox": "^5.1.1",
|
||||
@@ -46,7 +46,7 @@
|
||||
"jquery-ui": "^1.14.1",
|
||||
"jquery-validation": "^1.21.0",
|
||||
"jquery.iframe-transport": "^1.0.0",
|
||||
"jspdf-autotable": "^3.8.4",
|
||||
"jspdf-autotable": "^5.0.2",
|
||||
"less": "^4.2.2",
|
||||
"less-loader": "^6.0",
|
||||
"list.js": "^1.5.0",
|
||||
@@ -55,8 +55,7 @@
|
||||
"select2": "4.0.13",
|
||||
"sheetjs": "^2.0.0",
|
||||
"signature_pad": "^4.2.0",
|
||||
"tableexport.jquery.plugin": "1.32.0",
|
||||
"tether": "^1.4.0",
|
||||
"webpack": "^5.98.0"
|
||||
"tableexport.jquery.plugin": "^1.9.9",
|
||||
"tether": "^1.4.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1266,7 +1266,6 @@ label.form-control {
|
||||
}
|
||||
label.form-control--disabled {
|
||||
color: #959495;
|
||||
pointer-events: none;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
/** --------------------------------------- **/
|
||||
@@ -1429,6 +1428,9 @@ input[type="radio"]:checked::before {
|
||||
.bootstrap-table .fixed-table-container .table tbody tr .card-view {
|
||||
display: table-row !important;
|
||||
}
|
||||
.form-control-static {
|
||||
padding-top: 0px;
|
||||
}
|
||||
td.text-right.text-padding-number-cell {
|
||||
padding-right: 30px !important;
|
||||
white-space: nowrap;
|
||||
|
||||
@@ -887,7 +887,6 @@ label.form-control {
|
||||
}
|
||||
label.form-control--disabled {
|
||||
color: #959495;
|
||||
pointer-events: none;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
/** --------------------------------------- **/
|
||||
@@ -1050,6 +1049,9 @@ input[type="radio"]:checked::before {
|
||||
.bootstrap-table .fixed-table-container .table tbody tr .card-view {
|
||||
display: table-row !important;
|
||||
}
|
||||
.form-control-static {
|
||||
padding-top: 0px;
|
||||
}
|
||||
td.text-right.text-padding-number-cell {
|
||||
padding-right: 30px !important;
|
||||
white-space: nowrap;
|
||||
|
||||
8
public/css/dist/all.css
vendored
8
public/css/dist/all.css
vendored
@@ -22601,7 +22601,6 @@ label.form-control {
|
||||
}
|
||||
label.form-control--disabled {
|
||||
color: #959495;
|
||||
pointer-events: none;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
/** --------------------------------------- **/
|
||||
@@ -22764,6 +22763,9 @@ input[type="radio"]:checked::before {
|
||||
.bootstrap-table .fixed-table-container .table tbody tr .card-view {
|
||||
display: table-row !important;
|
||||
}
|
||||
.form-control-static {
|
||||
padding-top: 0px;
|
||||
}
|
||||
td.text-right.text-padding-number-cell {
|
||||
padding-right: 30px !important;
|
||||
white-space: nowrap;
|
||||
@@ -24174,7 +24176,6 @@ label.form-control {
|
||||
}
|
||||
label.form-control--disabled {
|
||||
color: #959495;
|
||||
pointer-events: none;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
/** --------------------------------------- **/
|
||||
@@ -24337,6 +24338,9 @@ input[type="radio"]:checked::before {
|
||||
.bootstrap-table .fixed-table-container .table tbody tr .card-view {
|
||||
display: table-row !important;
|
||||
}
|
||||
.form-control-static {
|
||||
padding-top: 0px;
|
||||
}
|
||||
td.text-right.text-padding-number-cell {
|
||||
padding-right: 30px !important;
|
||||
white-space: nowrap;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"/js/build/app.js": "/js/build/app.js?id=19253af36b58ed3fb6770c7bb944f079",
|
||||
"/css/dist/skins/skin-black-dark.css": "/css/dist/skins/skin-black-dark.css?id=78bfb1c7b5782df4fb0ac7e36f80f847",
|
||||
"/css/dist/skins/_all-skins.css": "/css/dist/skins/_all-skins.css?id=503d0b09e157a22f555e3670d1ec9bb5",
|
||||
"/css/build/overrides.css": "/css/build/overrides.css?id=2bfc7b71d951c5ac026dbc034f7373b1",
|
||||
"/css/build/app.css": "/css/build/app.css?id=4b4c2f1225d59efa7a22b76f7bbe39d8",
|
||||
"/css/build/overrides.css": "/css/build/overrides.css?id=a2147e7a0e0117ab3d20cce276e362e5",
|
||||
"/css/build/app.css": "/css/build/app.css?id=80d437dcee5ae27fc5e68f85beea4b09",
|
||||
"/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=f6b2e7fa795596ac4754500c9c30eacc",
|
||||
@@ -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=7aacfabbafd138c5af6420609f97820d",
|
||||
"/css/dist/skins/skin-black.css": "/css/dist/skins/skin-black.css?id=76482123f6c70e866d6b971ba91de7bb",
|
||||
"/css/dist/all.css": "/css/dist/all.css?id=12e96a25d0dc3ee39e9d3ce97044fbbf",
|
||||
"/css/dist/all.css": "/css/dist/all.css?id=c357227b5654c50afb9797141ac32dff",
|
||||
"/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",
|
||||
|
||||
255
public/vendor/livewire/livewire.esm.js
vendored
255
public/vendor/livewire/livewire.esm.js
vendored
@@ -2863,7 +2863,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
});
|
||||
return obj;
|
||||
}
|
||||
var Alpine20 = {
|
||||
var Alpine23 = {
|
||||
get reactive() {
|
||||
return reactive;
|
||||
},
|
||||
@@ -2876,7 +2876,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
get raw() {
|
||||
return raw;
|
||||
},
|
||||
version: "3.14.8",
|
||||
version: "3.14.9",
|
||||
flushAndStopDeferringMutations,
|
||||
dontAutoEvaluateFunctions,
|
||||
disableEffectScheduling,
|
||||
@@ -2929,7 +2929,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
data,
|
||||
bind: bind2
|
||||
};
|
||||
var alpine_default = Alpine20;
|
||||
var alpine_default = Alpine23;
|
||||
var import_reactivity10 = __toESM2(require_reactivity());
|
||||
magic("nextTick", () => nextTick);
|
||||
magic("dispatch", (el) => dispatch3.bind(dispatch3, el));
|
||||
@@ -3857,8 +3857,8 @@ var require_module_cjs2 = __commonJS({
|
||||
default: () => module_default
|
||||
});
|
||||
module.exports = __toCommonJS(module_exports);
|
||||
function src_default(Alpine20) {
|
||||
Alpine20.directive("collapse", collapse3);
|
||||
function src_default(Alpine23) {
|
||||
Alpine23.directive("collapse", collapse3);
|
||||
collapse3.inline = (el, { modifiers }) => {
|
||||
if (!modifiers.includes("min"))
|
||||
return;
|
||||
@@ -3878,7 +3878,7 @@ var require_module_cjs2 = __commonJS({
|
||||
if (!el._x_isShown)
|
||||
el.style.overflow = "hidden";
|
||||
let setFunction = (el2, styles) => {
|
||||
let revertFunction = Alpine20.setStyles(el2, styles);
|
||||
let revertFunction = Alpine23.setStyles(el2, styles);
|
||||
return styles.height ? () => {
|
||||
} : revertFunction;
|
||||
};
|
||||
@@ -3901,7 +3901,7 @@ var require_module_cjs2 = __commonJS({
|
||||
if (current === full) {
|
||||
current = floor;
|
||||
}
|
||||
Alpine20.transition(el, Alpine20.setStyles, {
|
||||
Alpine23.transition(el, Alpine23.setStyles, {
|
||||
during: transitionStyles,
|
||||
start: { height: current + "px" },
|
||||
end: { height: full + "px" }
|
||||
@@ -3915,7 +3915,7 @@ var require_module_cjs2 = __commonJS({
|
||||
}, after = () => {
|
||||
}) {
|
||||
let full = el.getBoundingClientRect().height;
|
||||
Alpine20.transition(el, setFunction, {
|
||||
Alpine23.transition(el, setFunction, {
|
||||
during: transitionStyles,
|
||||
start: { height: full + "px" },
|
||||
end: { height: floor + "px" }
|
||||
@@ -4751,14 +4751,14 @@ var require_module_cjs3 = __commonJS({
|
||||
module.exports = __toCommonJS(module_exports);
|
||||
var import_focus_trap = __toESM2(require_focus_trap());
|
||||
var import_tabbable = __toESM2(require_dist());
|
||||
function src_default(Alpine20) {
|
||||
function src_default(Alpine23) {
|
||||
let lastFocused;
|
||||
let currentFocused;
|
||||
window.addEventListener("focusin", () => {
|
||||
lastFocused = currentFocused;
|
||||
currentFocused = document.activeElement;
|
||||
});
|
||||
Alpine20.magic("focus", (el) => {
|
||||
Alpine23.magic("focus", (el) => {
|
||||
let within = el;
|
||||
return {
|
||||
__noscroll: false,
|
||||
@@ -4862,7 +4862,7 @@ var require_module_cjs3 = __commonJS({
|
||||
}
|
||||
};
|
||||
});
|
||||
Alpine20.directive("trap", Alpine20.skipDuringClone((el, { expression, modifiers }, { effect, evaluateLater, cleanup }) => {
|
||||
Alpine23.directive("trap", Alpine23.skipDuringClone((el, { expression, modifiers }, { effect, evaluateLater, cleanup }) => {
|
||||
let evaluator = evaluateLater(expression);
|
||||
let oldValue = false;
|
||||
let options = {
|
||||
@@ -4980,7 +4980,7 @@ var require_module_cjs4 = __commonJS({
|
||||
persist: () => src_default
|
||||
});
|
||||
module.exports = __toCommonJS(module_exports);
|
||||
function src_default(Alpine20) {
|
||||
function src_default(Alpine23) {
|
||||
let persist3 = () => {
|
||||
let alias;
|
||||
let storage;
|
||||
@@ -4995,11 +4995,11 @@ var require_module_cjs4 = __commonJS({
|
||||
setItem: dummy.set.bind(dummy)
|
||||
};
|
||||
}
|
||||
return Alpine20.interceptor((initialValue, getter, setter, path, key) => {
|
||||
return Alpine23.interceptor((initialValue, getter, setter, path, key) => {
|
||||
let lookup = alias || `_x_${path}`;
|
||||
let initial = storageHas(lookup, storage) ? storageGet(lookup, storage) : initialValue;
|
||||
setter(initial);
|
||||
Alpine20.effect(() => {
|
||||
Alpine23.effect(() => {
|
||||
let value = getter();
|
||||
storageSet(lookup, value, storage);
|
||||
setter(value);
|
||||
@@ -5015,12 +5015,12 @@ var require_module_cjs4 = __commonJS({
|
||||
};
|
||||
});
|
||||
};
|
||||
Object.defineProperty(Alpine20, "$persist", { get: () => persist3() });
|
||||
Alpine20.magic("persist", persist3);
|
||||
Alpine20.persist = (key, { get, set }, storage = localStorage) => {
|
||||
Object.defineProperty(Alpine23, "$persist", { get: () => persist3() });
|
||||
Alpine23.magic("persist", persist3);
|
||||
Alpine23.persist = (key, { get, set }, storage = localStorage) => {
|
||||
let initial = storageHas(key, storage) ? storageGet(key, storage) : get();
|
||||
set(initial);
|
||||
Alpine20.effect(() => {
|
||||
Alpine23.effect(() => {
|
||||
let value = get();
|
||||
storageSet(key, value, storage);
|
||||
set(value);
|
||||
@@ -5069,8 +5069,8 @@ var require_module_cjs5 = __commonJS({
|
||||
intersect: () => src_default
|
||||
});
|
||||
module.exports = __toCommonJS(module_exports);
|
||||
function src_default(Alpine20) {
|
||||
Alpine20.directive("intersect", Alpine20.skipDuringClone((el, { value, expression, modifiers }, { evaluateLater, cleanup }) => {
|
||||
function src_default(Alpine23) {
|
||||
Alpine23.directive("intersect", Alpine23.skipDuringClone((el, { value, expression, modifiers }, { evaluateLater, cleanup }) => {
|
||||
let evaluate = evaluateLater(expression);
|
||||
let options = {
|
||||
rootMargin: getRootMargin(modifiers),
|
||||
@@ -5151,8 +5151,8 @@ var require_module_cjs6 = __commonJS({
|
||||
resize: () => src_default
|
||||
});
|
||||
module.exports = __toCommonJS(module_exports);
|
||||
function src_default(Alpine20) {
|
||||
Alpine20.directive("resize", Alpine20.skipDuringClone((el, { value, expression, modifiers }, { evaluateLater, cleanup }) => {
|
||||
function src_default(Alpine23) {
|
||||
Alpine23.directive("resize", Alpine23.skipDuringClone((el, { value, expression, modifiers }, { evaluateLater, cleanup }) => {
|
||||
let evaluator = evaluateLater(expression);
|
||||
let evaluate = (width, height) => {
|
||||
evaluator(() => {
|
||||
@@ -6396,20 +6396,20 @@ var require_module_cjs7 = __commonJS({
|
||||
platform: platformWithCache
|
||||
});
|
||||
};
|
||||
function src_default(Alpine20) {
|
||||
Alpine20.magic("anchor", (el) => {
|
||||
function src_default(Alpine23) {
|
||||
Alpine23.magic("anchor", (el) => {
|
||||
if (!el._x_anchor)
|
||||
throw "Alpine: No x-anchor directive found on element using $anchor...";
|
||||
return el._x_anchor;
|
||||
});
|
||||
Alpine20.interceptClone((from, to) => {
|
||||
Alpine23.interceptClone((from, to) => {
|
||||
if (from && from._x_anchor && !to._x_anchor) {
|
||||
to._x_anchor = from._x_anchor;
|
||||
}
|
||||
});
|
||||
Alpine20.directive("anchor", Alpine20.skipDuringClone((el, { expression, modifiers, value }, { cleanup, evaluate: evaluate2 }) => {
|
||||
Alpine23.directive("anchor", Alpine23.skipDuringClone((el, { expression, modifiers, value }, { cleanup, evaluate: evaluate2 }) => {
|
||||
let { placement, offsetValue, unstyled } = getOptions(modifiers);
|
||||
el._x_anchor = Alpine20.reactive({ x: 0, y: 0 });
|
||||
el._x_anchor = Alpine23.reactive({ x: 0, y: 0 });
|
||||
let reference = evaluate2(expression);
|
||||
if (!reference)
|
||||
throw "Alpine: no element provided to x-anchor...";
|
||||
@@ -6784,7 +6784,8 @@ var require_module_cjs8 = __commonJS({
|
||||
return swapElements(from2, to);
|
||||
}
|
||||
let updateChildrenOnly = false;
|
||||
if (shouldSkip(updating, from2, to, () => updateChildrenOnly = true))
|
||||
let skipChildren = false;
|
||||
if (shouldSkipChildren(updating, () => skipChildren = true, from2, to, () => updateChildrenOnly = true))
|
||||
return;
|
||||
if (from2.nodeType === 1 && window.Alpine) {
|
||||
window.Alpine.cloneNode(from2, to);
|
||||
@@ -6801,8 +6802,10 @@ var require_module_cjs8 = __commonJS({
|
||||
patchAttributes(from2, to);
|
||||
}
|
||||
updated(from2, to);
|
||||
if (!skipChildren) {
|
||||
patchChildren(from2, to);
|
||||
}
|
||||
}
|
||||
function differentElementNamesTypesOrKeys(from2, to) {
|
||||
return from2.nodeType != to.nodeType || from2.nodeName != to.nodeName || getKey(from2) != getKey(to);
|
||||
}
|
||||
@@ -7015,6 +7018,11 @@ var require_module_cjs8 = __commonJS({
|
||||
hook(...args, () => skip = true);
|
||||
return skip;
|
||||
}
|
||||
function shouldSkipChildren(hook, skipChildren, ...args) {
|
||||
let skip = false;
|
||||
hook(...args, () => skip = true, skipChildren);
|
||||
return skip;
|
||||
}
|
||||
var patched = false;
|
||||
function createElement(html) {
|
||||
const template = document.createElement("template");
|
||||
@@ -7095,8 +7103,8 @@ var require_module_cjs8 = __commonJS({
|
||||
to.setAttribute("id", fromId);
|
||||
to.id = fromId;
|
||||
}
|
||||
function src_default(Alpine20) {
|
||||
Alpine20.morph = morph3;
|
||||
function src_default(Alpine23) {
|
||||
Alpine23.morph = morph3;
|
||||
}
|
||||
var module_default = src_default;
|
||||
}
|
||||
@@ -7129,8 +7137,8 @@ var require_module_cjs9 = __commonJS({
|
||||
stripDown: () => stripDown
|
||||
});
|
||||
module.exports = __toCommonJS(module_exports);
|
||||
function src_default(Alpine20) {
|
||||
Alpine20.directive("mask", (el, { value, expression }, { effect, evaluateLater, cleanup }) => {
|
||||
function src_default(Alpine23) {
|
||||
Alpine23.directive("mask", (el, { value, expression }, { effect, evaluateLater, cleanup }) => {
|
||||
let templateFn = () => expression;
|
||||
let lastInputValue = "";
|
||||
queueMicrotask(() => {
|
||||
@@ -7139,7 +7147,7 @@ var require_module_cjs9 = __commonJS({
|
||||
effect(() => {
|
||||
templateFn = (input) => {
|
||||
let result;
|
||||
Alpine20.dontAutoEvaluateFunctions(() => {
|
||||
Alpine23.dontAutoEvaluateFunctions(() => {
|
||||
evaluator((value2) => {
|
||||
result = typeof value2 === "function" ? value2(input) : value2;
|
||||
}, { scope: {
|
||||
@@ -8188,6 +8196,7 @@ var aliases = {
|
||||
"on": "$on",
|
||||
"el": "$el",
|
||||
"id": "$id",
|
||||
"js": "$js",
|
||||
"get": "$get",
|
||||
"set": "$set",
|
||||
"call": "$call",
|
||||
@@ -8259,6 +8268,14 @@ wireProperty("$el", (component) => {
|
||||
wireProperty("$id", (component) => {
|
||||
return component.id;
|
||||
});
|
||||
wireProperty("$js", (component) => {
|
||||
let fn = component.addJsAction.bind(component);
|
||||
let jsActions = component.getJsActions();
|
||||
Object.keys(jsActions).forEach((name) => {
|
||||
fn[name] = component.getJsAction(name);
|
||||
});
|
||||
return fn;
|
||||
});
|
||||
wireProperty("$set", (component) => async (property, value, live = true) => {
|
||||
dataSet(component.reactive, property, value);
|
||||
if (live) {
|
||||
@@ -8354,6 +8371,7 @@ var Component = class {
|
||||
this.ephemeral = extractData(deepClone(this.snapshot.data));
|
||||
this.reactive = Alpine.reactive(this.ephemeral);
|
||||
this.queuedUpdates = {};
|
||||
this.jsActions = {};
|
||||
this.$wire = generateWireObject(this, this.reactive);
|
||||
this.cleanups = [];
|
||||
this.processEffects(this.effects);
|
||||
@@ -8429,6 +8447,18 @@ var Component = class {
|
||||
}
|
||||
el.setAttribute("wire:effects", JSON.stringify(effects));
|
||||
}
|
||||
addJsAction(name, action) {
|
||||
this.jsActions[name] = action;
|
||||
}
|
||||
hasJsAction(name) {
|
||||
return this.jsActions[name] !== void 0;
|
||||
}
|
||||
getJsAction(name) {
|
||||
return this.jsActions[name].bind(this.$wire);
|
||||
}
|
||||
getJsActions() {
|
||||
return this.jsActions;
|
||||
}
|
||||
addCleanup(cleanup) {
|
||||
this.cleanups.push(cleanup);
|
||||
}
|
||||
@@ -9111,6 +9141,7 @@ var attributesExemptFromScriptTagHashing = [
|
||||
];
|
||||
function swapCurrentPageWithNewHtml(html, andThen) {
|
||||
let newDocument = new DOMParser().parseFromString(html, "text/html");
|
||||
let newHtml = newDocument.documentElement;
|
||||
let newBody = document.adoptNode(newDocument.body);
|
||||
let newHead = document.adoptNode(newDocument.head);
|
||||
oldBodyScriptTagHashes = oldBodyScriptTagHashes.concat(Array.from(document.body.querySelectorAll("script")).map((i) => {
|
||||
@@ -9118,6 +9149,7 @@ function swapCurrentPageWithNewHtml(html, andThen) {
|
||||
}));
|
||||
let afterRemoteScriptsHaveLoaded = () => {
|
||||
};
|
||||
replaceHtmlAttributes(newHtml);
|
||||
mergeNewHead(newHead).finally(() => {
|
||||
afterRemoteScriptsHaveLoaded();
|
||||
});
|
||||
@@ -9137,6 +9169,21 @@ function prepNewBodyScriptTagsToRun(newBody, oldBodyScriptTagHashes2) {
|
||||
i.replaceWith(cloneScriptTag(i));
|
||||
});
|
||||
}
|
||||
function replaceHtmlAttributes(newHtmlElement) {
|
||||
let currentHtmlElement = document.documentElement;
|
||||
Array.from(newHtmlElement.attributes).forEach((attr) => {
|
||||
const name = attr.name;
|
||||
const value = attr.value;
|
||||
if (currentHtmlElement.getAttribute(name) !== value) {
|
||||
currentHtmlElement.setAttribute(name, value);
|
||||
}
|
||||
});
|
||||
Array.from(currentHtmlElement.attributes).forEach((attr) => {
|
||||
if (!newHtmlElement.hasAttribute(attr.name)) {
|
||||
currentHtmlElement.removeAttribute(attr.name);
|
||||
}
|
||||
});
|
||||
}
|
||||
function mergeNewHead(newHead) {
|
||||
let children = Array.from(document.head.children);
|
||||
let headChildrenHtmlLookup = children.map((i) => i.outerHTML);
|
||||
@@ -9240,8 +9287,8 @@ var enablePersist = true;
|
||||
var showProgressBar = true;
|
||||
var restoreScroll = true;
|
||||
var autofocus = false;
|
||||
function navigate_default(Alpine20) {
|
||||
Alpine20.navigate = (url) => {
|
||||
function navigate_default(Alpine23) {
|
||||
Alpine23.navigate = (url) => {
|
||||
let destination = createUrlObjectFromString(url);
|
||||
let prevented = fireEventForOtherLibrariesToHookInto("alpine:navigate", {
|
||||
url: destination,
|
||||
@@ -9252,11 +9299,11 @@ function navigate_default(Alpine20) {
|
||||
return;
|
||||
navigateTo(destination);
|
||||
};
|
||||
Alpine20.navigate.disableProgressBar = () => {
|
||||
Alpine23.navigate.disableProgressBar = () => {
|
||||
showProgressBar = false;
|
||||
};
|
||||
Alpine20.addInitSelector(() => `[${Alpine20.prefixed("navigate")}]`);
|
||||
Alpine20.directive("navigate", (el, { modifiers }) => {
|
||||
Alpine23.addInitSelector(() => `[${Alpine23.prefixed("navigate")}]`);
|
||||
Alpine23.directive("navigate", (el, { modifiers }) => {
|
||||
let shouldPrefetchOnHover = modifiers.includes("hover");
|
||||
shouldPrefetchOnHover && whenThisLinkIsHoveredFor(el, 60, () => {
|
||||
let destination = extractDestinationFromLink(el);
|
||||
@@ -9293,7 +9340,7 @@ function navigate_default(Alpine20) {
|
||||
showProgressBar && finishAndHideProgressBar();
|
||||
cleanupAlpineElementsOnThePageThatArentInsideAPersistedElement();
|
||||
updateCurrentPageHtmlInHistoryStateForLaterBackButtonClicks();
|
||||
preventAlpineFromPickingUpDomChanges(Alpine20, (andAfterAllThis) => {
|
||||
preventAlpineFromPickingUpDomChanges(Alpine23, (andAfterAllThis) => {
|
||||
enablePersist && storePersistantElementsForLater((persistedEl) => {
|
||||
packUpPersistedTeleports(persistedEl);
|
||||
packUpPersistedPopovers(persistedEl);
|
||||
@@ -9315,7 +9362,7 @@ function navigate_default(Alpine20) {
|
||||
setTimeout(() => {
|
||||
autofocus && autofocusElementsWithTheAutofocusAttribute();
|
||||
});
|
||||
nowInitializeAlpineOnTheNewPage(Alpine20);
|
||||
nowInitializeAlpineOnTheNewPage(Alpine23);
|
||||
fireEventForOtherLibrariesToHookInto("alpine:navigated");
|
||||
});
|
||||
});
|
||||
@@ -9348,7 +9395,7 @@ function navigate_default(Alpine20) {
|
||||
storeScrollInformationInHtmlBeforeNavigatingAway();
|
||||
fireEventForOtherLibrariesToHookInto("alpine:navigating");
|
||||
updateCurrentPageHtmlInSnapshotCacheForLaterBackButtonClicks(currentPageUrl, currentPageKey);
|
||||
preventAlpineFromPickingUpDomChanges(Alpine20, (andAfterAllThis) => {
|
||||
preventAlpineFromPickingUpDomChanges(Alpine23, (andAfterAllThis) => {
|
||||
enablePersist && storePersistantElementsForLater((persistedEl) => {
|
||||
packUpPersistedTeleports(persistedEl);
|
||||
packUpPersistedPopovers(persistedEl);
|
||||
@@ -9363,7 +9410,7 @@ function navigate_default(Alpine20) {
|
||||
restoreScrollPositionOrScrollToTop();
|
||||
andAfterAllThis(() => {
|
||||
autofocus && autofocusElementsWithTheAutofocusAttribute();
|
||||
nowInitializeAlpineOnTheNewPage(Alpine20);
|
||||
nowInitializeAlpineOnTheNewPage(Alpine23);
|
||||
fireEventForOtherLibrariesToHookInto("alpine:navigated");
|
||||
});
|
||||
});
|
||||
@@ -9378,10 +9425,10 @@ function fetchHtmlOrUsePrefetchedHtml(fromDestination, callback) {
|
||||
fetchHtml(fromDestination, callback);
|
||||
});
|
||||
}
|
||||
function preventAlpineFromPickingUpDomChanges(Alpine20, callback) {
|
||||
Alpine20.stopObservingMutations();
|
||||
function preventAlpineFromPickingUpDomChanges(Alpine23, callback) {
|
||||
Alpine23.stopObservingMutations();
|
||||
callback((afterAllThis) => {
|
||||
Alpine20.startObservingMutations();
|
||||
Alpine23.startObservingMutations();
|
||||
queueMicrotask(() => {
|
||||
afterAllThis();
|
||||
});
|
||||
@@ -9396,8 +9443,8 @@ function fireEventForOtherLibrariesToHookInto(name, detail) {
|
||||
document.dispatchEvent(event);
|
||||
return event.defaultPrevented;
|
||||
}
|
||||
function nowInitializeAlpineOnTheNewPage(Alpine20) {
|
||||
Alpine20.initTree(document.body, void 0, (el, skip) => {
|
||||
function nowInitializeAlpineOnTheNewPage(Alpine23) {
|
||||
Alpine23.initTree(document.body, void 0, (el, skip) => {
|
||||
if (el._x_wasPersisted)
|
||||
skip();
|
||||
});
|
||||
@@ -9420,8 +9467,8 @@ function cleanupAlpineElementsOnThePageThatArentInsideAPersistedElement() {
|
||||
}
|
||||
|
||||
// js/plugins/history/index.js
|
||||
function history2(Alpine20) {
|
||||
Alpine20.magic("queryString", (el, { interceptor }) => {
|
||||
function history2(Alpine23) {
|
||||
Alpine23.magic("queryString", (el, { interceptor }) => {
|
||||
let alias;
|
||||
let alwaysShow = false;
|
||||
let usePush = false;
|
||||
@@ -9430,9 +9477,9 @@ function history2(Alpine20) {
|
||||
let { initial, replace: replace2, push: push2, pop } = track(queryKey, initialSeedValue, alwaysShow);
|
||||
setter(initial);
|
||||
if (!usePush) {
|
||||
Alpine20.effect(() => replace2(getter()));
|
||||
Alpine23.effect(() => replace2(getter()));
|
||||
} else {
|
||||
Alpine20.effect(() => push2(getter()));
|
||||
Alpine23.effect(() => push2(getter()));
|
||||
pop(async (newValue) => {
|
||||
setter(newValue);
|
||||
let tillTheEndOfTheMicrotaskQueue = () => Promise.resolve();
|
||||
@@ -9455,7 +9502,7 @@ function history2(Alpine20) {
|
||||
};
|
||||
});
|
||||
});
|
||||
Alpine20.history = { track };
|
||||
Alpine23.history = { track };
|
||||
}
|
||||
function track(name, initialSeedValue, alwaysShow = false, except = null) {
|
||||
let { has, get, set, remove } = queryStringUtils();
|
||||
@@ -9519,14 +9566,22 @@ function replace(url, key, object) {
|
||||
if (!state.alpine)
|
||||
state.alpine = {};
|
||||
state.alpine[key] = unwrap(object);
|
||||
try {
|
||||
window.history.replaceState(state, "", url.toString());
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
function push(url, key, object) {
|
||||
let state = window.history.state || {};
|
||||
if (!state.alpine)
|
||||
state.alpine = {};
|
||||
state = { alpine: { ...state.alpine, ...{ [key]: unwrap(object) } } };
|
||||
try {
|
||||
window.history.pushState(state, "", url.toString());
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
function unwrap(object) {
|
||||
if (object === void 0)
|
||||
@@ -9697,7 +9752,7 @@ function ensureLivewireScriptIsntMisplaced() {
|
||||
}
|
||||
|
||||
// js/index.js
|
||||
var import_alpinejs18 = __toESM(require_module_cjs());
|
||||
var import_alpinejs21 = __toESM(require_module_cjs());
|
||||
|
||||
// js/features/supportListeners.js
|
||||
on("effect", ({ component, effects }) => {
|
||||
@@ -9754,7 +9809,7 @@ on("effect", ({ component, effects }) => {
|
||||
onlyIfScriptHasntBeenRunAlreadyForThisComponent(component, key, () => {
|
||||
let scriptContent = extractScriptTagContent(content);
|
||||
import_alpinejs6.default.dontAutoEvaluateFunctions(() => {
|
||||
import_alpinejs6.default.evaluate(component.el, scriptContent, { "$wire": component.$wire });
|
||||
import_alpinejs6.default.evaluate(component.el, scriptContent, { "$wire": component.$wire, "$js": component.$wire.$js });
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -9827,6 +9882,10 @@ function cloneScriptTag2(el) {
|
||||
|
||||
// js/features/supportJsEvaluation.js
|
||||
var import_alpinejs7 = __toESM(require_module_cjs());
|
||||
import_alpinejs7.default.magic("js", (el) => {
|
||||
let component = closestComponent(el);
|
||||
return component.$wire.js;
|
||||
});
|
||||
on("effect", ({ component, effects }) => {
|
||||
let js = effects.js;
|
||||
let xjs = effects.xjs;
|
||||
@@ -9838,8 +9897,9 @@ on("effect", ({ component, effects }) => {
|
||||
});
|
||||
}
|
||||
if (xjs) {
|
||||
xjs.forEach((expression) => {
|
||||
import_alpinejs7.default.evaluate(component.el, expression);
|
||||
xjs.forEach(({ expression, params }) => {
|
||||
params = Object.values(params);
|
||||
import_alpinejs7.default.evaluate(component.el, expression, { scope: component.jsActions, params });
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -9860,10 +9920,10 @@ function morph2(component, el, html) {
|
||||
to.__livewire = component;
|
||||
trigger("morph", { el, toEl: to, component });
|
||||
import_alpinejs8.default.morph(el, to, {
|
||||
updating: (el2, toEl, childrenOnly, skip) => {
|
||||
updating: (el2, toEl, childrenOnly, skip, skipChildren) => {
|
||||
if (isntElement(el2))
|
||||
return;
|
||||
trigger("morph.updating", { el: el2, toEl, component, skip, childrenOnly });
|
||||
trigger("morph.updating", { el: el2, toEl, component, skip, childrenOnly, skipChildren });
|
||||
if (el2.__livewire_replace === true)
|
||||
el2.innerHTML = toEl.innerHTML;
|
||||
if (el2.__livewire_replace_self === true) {
|
||||
@@ -9874,6 +9934,8 @@ function morph2(component, el, html) {
|
||||
return skip();
|
||||
if (el2.__livewire_ignore_self === true)
|
||||
childrenOnly();
|
||||
if (el2.__livewire_ignore_children === true)
|
||||
return skipChildren();
|
||||
if (isComponentRootEl(el2) && el2.getAttribute("wire:id") !== component.id)
|
||||
return skip();
|
||||
if (isComponentRootEl(el2))
|
||||
@@ -10309,6 +10371,14 @@ on("morph.added", ({ el }) => {
|
||||
el.__addedByMorph = true;
|
||||
});
|
||||
directive("transition", ({ el, directive: directive2, component, cleanup }) => {
|
||||
for (let i = 0; i < el.attributes.length; i++) {
|
||||
if (el.attributes[i].name.startsWith("wire:show")) {
|
||||
import_alpinejs11.default.bind(el, {
|
||||
[directive2.rawName.replace("wire:transition", "x-transition")]: directive2.expression
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
let visibility = import_alpinejs11.default.reactive({ state: el.__addedByMorph ? false : true });
|
||||
import_alpinejs11.default.bind(el, {
|
||||
[directive2.rawName.replace("wire:", "x-")]: "",
|
||||
@@ -10446,8 +10516,10 @@ globalDirective("current", ({ el, directive: directive2, cleanup }) => {
|
||||
let refreshCurrent = (url) => {
|
||||
if (pathMatches(hrefUrl, url, options)) {
|
||||
el.classList.add(...classes);
|
||||
el.setAttribute("data-current", "");
|
||||
} else {
|
||||
el.classList.remove(...classes);
|
||||
el.removeAttribute("data-current");
|
||||
}
|
||||
};
|
||||
refreshCurrent(new URL(window.location.href));
|
||||
@@ -10735,15 +10807,25 @@ directive("replace", ({ el, directive: directive2 }) => {
|
||||
directive("ignore", ({ el, directive: directive2 }) => {
|
||||
if (directive2.modifiers.includes("self")) {
|
||||
el.__livewire_ignore_self = true;
|
||||
} else if (directive2.modifiers.includes("children")) {
|
||||
el.__livewire_ignore_children = true;
|
||||
} else {
|
||||
el.__livewire_ignore = true;
|
||||
}
|
||||
});
|
||||
|
||||
// js/directives/wire-cloak.js
|
||||
var import_alpinejs15 = __toESM(require_module_cjs());
|
||||
import_alpinejs15.default.interceptInit((el) => {
|
||||
if (el.hasAttribute("wire:cloak")) {
|
||||
import_alpinejs15.default.mutateDom(() => el.removeAttribute("wire:cloak"));
|
||||
}
|
||||
});
|
||||
|
||||
// js/directives/wire-dirty.js
|
||||
var refreshDirtyStatesByComponent = new WeakBag();
|
||||
on("commit", ({ component, succeed }) => {
|
||||
succeed(() => {
|
||||
on("commit", ({ component, respond }) => {
|
||||
respond(() => {
|
||||
setTimeout(() => {
|
||||
refreshDirtyStatesByComponent.each(component, (i) => i(false));
|
||||
});
|
||||
@@ -10751,7 +10833,6 @@ on("commit", ({ component, succeed }) => {
|
||||
});
|
||||
directive("dirty", ({ el, directive: directive2, component }) => {
|
||||
let targets = dirtyTargets(el);
|
||||
let dirty = Alpine.reactive({ state: false });
|
||||
let oldIsDirty = false;
|
||||
let initialDisplay = el.style.display;
|
||||
let refreshDirtyState = (isDirty) => {
|
||||
@@ -10790,7 +10871,7 @@ function dirtyTargets(el) {
|
||||
}
|
||||
|
||||
// js/directives/wire-model.js
|
||||
var import_alpinejs15 = __toESM(require_module_cjs());
|
||||
var import_alpinejs16 = __toESM(require_module_cjs());
|
||||
directive("model", ({ el, directive: directive2, component, cleanup }) => {
|
||||
let { expression, modifiers } = directive2;
|
||||
if (!expression) {
|
||||
@@ -10808,7 +10889,7 @@ directive("model", ({ el, directive: directive2, component, cleanup }) => {
|
||||
let isDebounced = modifiers.includes("debounce");
|
||||
let update = expression.startsWith("$parent") ? () => component.$wire.$parent.$commit() : () => component.$wire.$commit();
|
||||
let debouncedUpdate = isTextInput(el) && !isDebounced && isLive ? debounce(update, 150) : update;
|
||||
import_alpinejs15.default.bind(el, {
|
||||
import_alpinejs16.default.bind(el, {
|
||||
["@change"]() {
|
||||
isLazy && update();
|
||||
},
|
||||
@@ -10864,14 +10945,14 @@ function debounce(func, wait) {
|
||||
}
|
||||
|
||||
// js/directives/wire-init.js
|
||||
var import_alpinejs16 = __toESM(require_module_cjs());
|
||||
var import_alpinejs17 = __toESM(require_module_cjs());
|
||||
directive("init", ({ el, directive: directive2 }) => {
|
||||
let fullMethod = directive2.expression ?? "$refresh";
|
||||
import_alpinejs16.default.evaluate(el, `$wire.${fullMethod}`);
|
||||
import_alpinejs17.default.evaluate(el, `$wire.${fullMethod}`);
|
||||
});
|
||||
|
||||
// js/directives/wire-poll.js
|
||||
var import_alpinejs17 = __toESM(require_module_cjs());
|
||||
var import_alpinejs18 = __toESM(require_module_cjs());
|
||||
directive("poll", ({ el, directive: directive2 }) => {
|
||||
let interval = extractDurationFrom(directive2.modifiers, 2e3);
|
||||
let { start: start2, pauseWhile, throttleWhile, stopWhen } = poll(() => {
|
||||
@@ -10885,7 +10966,7 @@ directive("poll", ({ el, directive: directive2 }) => {
|
||||
stopWhen(() => theElementIsDisconnected(el));
|
||||
});
|
||||
function triggerComponentRequest(el, directive2) {
|
||||
import_alpinejs17.default.evaluate(el, directive2.expression ? "$wire." + directive2.expression : "$wire.$commit()");
|
||||
import_alpinejs18.default.evaluate(el, directive2.expression ? "$wire." + directive2.expression : "$wire.$commit()");
|
||||
}
|
||||
function poll(callback, interval = 2e3) {
|
||||
let pauseConditions = [];
|
||||
@@ -10973,6 +11054,40 @@ function extractDurationFrom(modifiers, defaultDuration) {
|
||||
return durationInMilliSeconds || defaultDuration;
|
||||
}
|
||||
|
||||
// js/directives/wire-show.js
|
||||
var import_alpinejs19 = __toESM(require_module_cjs());
|
||||
import_alpinejs19.default.interceptInit((el) => {
|
||||
for (let i = 0; i < el.attributes.length; i++) {
|
||||
if (el.attributes[i].name.startsWith("wire:show")) {
|
||||
let { name, value } = el.attributes[i];
|
||||
let modifierString = name.split("wire:show")[1];
|
||||
let expression = value.startsWith("!") ? "!$wire." + value.slice(1).trim() : "$wire." + value.trim();
|
||||
import_alpinejs19.default.bind(el, {
|
||||
["x-show" + modifierString]() {
|
||||
return import_alpinejs19.default.evaluate(el, expression);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// js/directives/wire-text.js
|
||||
var import_alpinejs20 = __toESM(require_module_cjs());
|
||||
import_alpinejs20.default.interceptInit((el) => {
|
||||
for (let i = 0; i < el.attributes.length; i++) {
|
||||
if (el.attributes[i].name.startsWith("wire:text")) {
|
||||
let { name, value } = el.attributes[i];
|
||||
let modifierString = name.split("wire:text")[1];
|
||||
let expression = value.startsWith("!") ? "!$wire." + value.slice(1).trim() : "$wire." + value.trim();
|
||||
import_alpinejs20.default.bind(el, {
|
||||
["x-text" + modifierString]() {
|
||||
return import_alpinejs20.default.evaluate(el, expression);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// js/index.js
|
||||
var Livewire2 = {
|
||||
directive,
|
||||
@@ -10988,7 +11103,7 @@ var Livewire2 = {
|
||||
dispatch: dispatchGlobal,
|
||||
on: on2,
|
||||
get navigate() {
|
||||
return import_alpinejs18.default.navigate;
|
||||
return import_alpinejs21.default.navigate;
|
||||
}
|
||||
};
|
||||
var warnAboutMultipleInstancesOf = (entity) => console.warn(`Detected multiple instances of ${entity} running`);
|
||||
@@ -10997,7 +11112,7 @@ if (window.Livewire)
|
||||
if (window.Alpine)
|
||||
warnAboutMultipleInstancesOf("Alpine");
|
||||
window.Livewire = Livewire2;
|
||||
window.Alpine = import_alpinejs18.default;
|
||||
window.Alpine = import_alpinejs21.default;
|
||||
if (window.livewireScriptConfig === void 0) {
|
||||
window.Alpine.__fromLivewire = true;
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
@@ -11007,7 +11122,7 @@ if (window.livewireScriptConfig === void 0) {
|
||||
Livewire2.start();
|
||||
});
|
||||
}
|
||||
var export_Alpine = import_alpinejs18.default;
|
||||
var export_Alpine = import_alpinejs21.default;
|
||||
export {
|
||||
export_Alpine as Alpine,
|
||||
Livewire2 as Livewire
|
||||
|
||||
6
public/vendor/livewire/livewire.esm.js.map
vendored
6
public/vendor/livewire/livewire.esm.js.map
vendored
File diff suppressed because one or more lines are too long
132
public/vendor/livewire/livewire.js
vendored
132
public/vendor/livewire/livewire.js
vendored
@@ -2295,7 +2295,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
get raw() {
|
||||
return raw;
|
||||
},
|
||||
version: "3.14.8",
|
||||
version: "3.14.9",
|
||||
flushAndStopDeferringMutations,
|
||||
dontAutoEvaluateFunctions,
|
||||
disableEffectScheduling,
|
||||
@@ -4363,6 +4363,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
"on": "$on",
|
||||
"el": "$el",
|
||||
"id": "$id",
|
||||
"js": "$js",
|
||||
"get": "$get",
|
||||
"set": "$set",
|
||||
"call": "$call",
|
||||
@@ -4434,6 +4435,14 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
wireProperty("$id", (component) => {
|
||||
return component.id;
|
||||
});
|
||||
wireProperty("$js", (component) => {
|
||||
let fn = component.addJsAction.bind(component);
|
||||
let jsActions = component.getJsActions();
|
||||
Object.keys(jsActions).forEach((name) => {
|
||||
fn[name] = component.getJsAction(name);
|
||||
});
|
||||
return fn;
|
||||
});
|
||||
wireProperty("$set", (component) => async (property, value, live = true) => {
|
||||
dataSet(component.reactive, property, value);
|
||||
if (live) {
|
||||
@@ -4529,6 +4538,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
this.ephemeral = extractData(deepClone(this.snapshot.data));
|
||||
this.reactive = Alpine.reactive(this.ephemeral);
|
||||
this.queuedUpdates = {};
|
||||
this.jsActions = {};
|
||||
this.$wire = generateWireObject(this, this.reactive);
|
||||
this.cleanups = [];
|
||||
this.processEffects(this.effects);
|
||||
@@ -4604,6 +4614,18 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
}
|
||||
el.setAttribute("wire:effects", JSON.stringify(effects));
|
||||
}
|
||||
addJsAction(name, action) {
|
||||
this.jsActions[name] = action;
|
||||
}
|
||||
hasJsAction(name) {
|
||||
return this.jsActions[name] !== void 0;
|
||||
}
|
||||
getJsAction(name) {
|
||||
return this.jsActions[name].bind(this.$wire);
|
||||
}
|
||||
getJsActions() {
|
||||
return this.jsActions;
|
||||
}
|
||||
addCleanup(cleanup2) {
|
||||
this.cleanups.push(cleanup2);
|
||||
}
|
||||
@@ -7715,6 +7737,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
];
|
||||
function swapCurrentPageWithNewHtml(html, andThen) {
|
||||
let newDocument = new DOMParser().parseFromString(html, "text/html");
|
||||
let newHtml = newDocument.documentElement;
|
||||
let newBody = document.adoptNode(newDocument.body);
|
||||
let newHead = document.adoptNode(newDocument.head);
|
||||
oldBodyScriptTagHashes = oldBodyScriptTagHashes.concat(Array.from(document.body.querySelectorAll("script")).map((i) => {
|
||||
@@ -7722,6 +7745,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
}));
|
||||
let afterRemoteScriptsHaveLoaded = () => {
|
||||
};
|
||||
replaceHtmlAttributes(newHtml);
|
||||
mergeNewHead(newHead).finally(() => {
|
||||
afterRemoteScriptsHaveLoaded();
|
||||
});
|
||||
@@ -7741,6 +7765,21 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
i.replaceWith(cloneScriptTag(i));
|
||||
});
|
||||
}
|
||||
function replaceHtmlAttributes(newHtmlElement) {
|
||||
let currentHtmlElement = document.documentElement;
|
||||
Array.from(newHtmlElement.attributes).forEach((attr) => {
|
||||
const name = attr.name;
|
||||
const value = attr.value;
|
||||
if (currentHtmlElement.getAttribute(name) !== value) {
|
||||
currentHtmlElement.setAttribute(name, value);
|
||||
}
|
||||
});
|
||||
Array.from(currentHtmlElement.attributes).forEach((attr) => {
|
||||
if (!newHtmlElement.hasAttribute(attr.name)) {
|
||||
currentHtmlElement.removeAttribute(attr.name);
|
||||
}
|
||||
});
|
||||
}
|
||||
function mergeNewHead(newHead) {
|
||||
let children = Array.from(document.head.children);
|
||||
let headChildrenHtmlLookup = children.map((i) => i.outerHTML);
|
||||
@@ -8123,14 +8162,22 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
if (!state.alpine)
|
||||
state.alpine = {};
|
||||
state.alpine[key] = unwrap(object);
|
||||
try {
|
||||
window.history.replaceState(state, "", url.toString());
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
function push(url, key, object) {
|
||||
let state = window.history.state || {};
|
||||
if (!state.alpine)
|
||||
state.alpine = {};
|
||||
state = { alpine: { ...state.alpine, ...{ [key]: unwrap(object) } } };
|
||||
try {
|
||||
window.history.pushState(state, "", url.toString());
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
function unwrap(object) {
|
||||
if (object === void 0)
|
||||
@@ -8251,7 +8298,8 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
return swapElements(from2, to);
|
||||
}
|
||||
let updateChildrenOnly = false;
|
||||
if (shouldSkip(updating, from2, to, () => updateChildrenOnly = true))
|
||||
let skipChildren = false;
|
||||
if (shouldSkipChildren(updating, () => skipChildren = true, from2, to, () => updateChildrenOnly = true))
|
||||
return;
|
||||
if (from2.nodeType === 1 && window.Alpine) {
|
||||
window.Alpine.cloneNode(from2, to);
|
||||
@@ -8268,8 +8316,10 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
patchAttributes(from2, to);
|
||||
}
|
||||
updated(from2, to);
|
||||
if (!skipChildren) {
|
||||
patchChildren(from2, to);
|
||||
}
|
||||
}
|
||||
function differentElementNamesTypesOrKeys(from2, to) {
|
||||
return from2.nodeType != to.nodeType || from2.nodeName != to.nodeName || getKey(from2) != getKey(to);
|
||||
}
|
||||
@@ -8482,6 +8532,11 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
hook(...args, () => skip = true);
|
||||
return skip;
|
||||
}
|
||||
function shouldSkipChildren(hook, skipChildren, ...args) {
|
||||
let skip = false;
|
||||
hook(...args, () => skip = true, skipChildren);
|
||||
return skip;
|
||||
}
|
||||
var patched = false;
|
||||
function createElement(html) {
|
||||
const template = document.createElement("template");
|
||||
@@ -8861,7 +8916,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
onlyIfScriptHasntBeenRunAlreadyForThisComponent(component, key, () => {
|
||||
let scriptContent = extractScriptTagContent(content);
|
||||
module_default.dontAutoEvaluateFunctions(() => {
|
||||
module_default.evaluate(component.el, scriptContent, { "$wire": component.$wire });
|
||||
module_default.evaluate(component.el, scriptContent, { "$wire": component.$wire, "$js": component.$wire.$js });
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -8933,6 +8988,10 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
}
|
||||
|
||||
// js/features/supportJsEvaluation.js
|
||||
module_default.magic("js", (el) => {
|
||||
let component = closestComponent(el);
|
||||
return component.$wire.js;
|
||||
});
|
||||
on2("effect", ({ component, effects }) => {
|
||||
let js = effects.js;
|
||||
let xjs = effects.xjs;
|
||||
@@ -8944,8 +9003,9 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
});
|
||||
}
|
||||
if (xjs) {
|
||||
xjs.forEach((expression) => {
|
||||
module_default.evaluate(component.el, expression);
|
||||
xjs.forEach(({ expression, params }) => {
|
||||
params = Object.values(params);
|
||||
module_default.evaluate(component.el, expression, { scope: component.jsActions, params });
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -8965,10 +9025,10 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
to.__livewire = component;
|
||||
trigger2("morph", { el, toEl: to, component });
|
||||
module_default.morph(el, to, {
|
||||
updating: (el2, toEl, childrenOnly, skip) => {
|
||||
updating: (el2, toEl, childrenOnly, skip, skipChildren) => {
|
||||
if (isntElement(el2))
|
||||
return;
|
||||
trigger2("morph.updating", { el: el2, toEl, component, skip, childrenOnly });
|
||||
trigger2("morph.updating", { el: el2, toEl, component, skip, childrenOnly, skipChildren });
|
||||
if (el2.__livewire_replace === true)
|
||||
el2.innerHTML = toEl.innerHTML;
|
||||
if (el2.__livewire_replace_self === true) {
|
||||
@@ -8979,6 +9039,8 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
return skip();
|
||||
if (el2.__livewire_ignore_self === true)
|
||||
childrenOnly();
|
||||
if (el2.__livewire_ignore_children === true)
|
||||
return skipChildren();
|
||||
if (isComponentRootEl(el2) && el2.getAttribute("wire:id") !== component.id)
|
||||
return skip();
|
||||
if (isComponentRootEl(el2))
|
||||
@@ -9411,6 +9473,14 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
el.__addedByMorph = true;
|
||||
});
|
||||
directive2("transition", ({ el, directive: directive3, component, cleanup: cleanup2 }) => {
|
||||
for (let i = 0; i < el.attributes.length; i++) {
|
||||
if (el.attributes[i].name.startsWith("wire:show")) {
|
||||
module_default.bind(el, {
|
||||
[directive3.rawName.replace("wire:transition", "x-transition")]: directive3.expression
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
let visibility = module_default.reactive({ state: el.__addedByMorph ? false : true });
|
||||
module_default.bind(el, {
|
||||
[directive3.rawName.replace("wire:", "x-")]: "",
|
||||
@@ -9545,8 +9615,10 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
let refreshCurrent = (url) => {
|
||||
if (pathMatches(hrefUrl, url, options)) {
|
||||
el.classList.add(...classes);
|
||||
el.setAttribute("data-current", "");
|
||||
} else {
|
||||
el.classList.remove(...classes);
|
||||
el.removeAttribute("data-current");
|
||||
}
|
||||
};
|
||||
refreshCurrent(new URL(window.location.href));
|
||||
@@ -9834,15 +9906,24 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
directive2("ignore", ({ el, directive: directive3 }) => {
|
||||
if (directive3.modifiers.includes("self")) {
|
||||
el.__livewire_ignore_self = true;
|
||||
} else if (directive3.modifiers.includes("children")) {
|
||||
el.__livewire_ignore_children = true;
|
||||
} else {
|
||||
el.__livewire_ignore = true;
|
||||
}
|
||||
});
|
||||
|
||||
// js/directives/wire-cloak.js
|
||||
module_default.interceptInit((el) => {
|
||||
if (el.hasAttribute("wire:cloak")) {
|
||||
module_default.mutateDom(() => el.removeAttribute("wire:cloak"));
|
||||
}
|
||||
});
|
||||
|
||||
// js/directives/wire-dirty.js
|
||||
var refreshDirtyStatesByComponent = new WeakBag();
|
||||
on2("commit", ({ component, succeed }) => {
|
||||
succeed(() => {
|
||||
on2("commit", ({ component, respond }) => {
|
||||
respond(() => {
|
||||
setTimeout(() => {
|
||||
refreshDirtyStatesByComponent.each(component, (i) => i(false));
|
||||
});
|
||||
@@ -9850,7 +9931,6 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
});
|
||||
directive2("dirty", ({ el, directive: directive3, component }) => {
|
||||
let targets = dirtyTargets(el);
|
||||
let dirty = Alpine.reactive({ state: false });
|
||||
let oldIsDirty = false;
|
||||
let initialDisplay = el.style.display;
|
||||
let refreshDirtyState = (isDirty) => {
|
||||
@@ -10069,6 +10149,38 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
||||
return durationInMilliSeconds || defaultDuration;
|
||||
}
|
||||
|
||||
// js/directives/wire-show.js
|
||||
module_default.interceptInit((el) => {
|
||||
for (let i = 0; i < el.attributes.length; i++) {
|
||||
if (el.attributes[i].name.startsWith("wire:show")) {
|
||||
let { name, value } = el.attributes[i];
|
||||
let modifierString = name.split("wire:show")[1];
|
||||
let expression = value.startsWith("!") ? "!$wire." + value.slice(1).trim() : "$wire." + value.trim();
|
||||
module_default.bind(el, {
|
||||
["x-show" + modifierString]() {
|
||||
return module_default.evaluate(el, expression);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// js/directives/wire-text.js
|
||||
module_default.interceptInit((el) => {
|
||||
for (let i = 0; i < el.attributes.length; i++) {
|
||||
if (el.attributes[i].name.startsWith("wire:text")) {
|
||||
let { name, value } = el.attributes[i];
|
||||
let modifierString = name.split("wire:text")[1];
|
||||
let expression = value.startsWith("!") ? "!$wire." + value.slice(1).trim() : "$wire." + value.trim();
|
||||
module_default.bind(el, {
|
||||
["x-text" + modifierString]() {
|
||||
return module_default.evaluate(el, expression);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// js/index.js
|
||||
var Livewire2 = {
|
||||
directive: directive2,
|
||||
|
||||
12
public/vendor/livewire/livewire.min.js
vendored
12
public/vendor/livewire/livewire.min.js
vendored
File diff suppressed because one or more lines are too long
6
public/vendor/livewire/livewire.min.js.map
vendored
6
public/vendor/livewire/livewire.min.js.map
vendored
File diff suppressed because one or more lines are too long
2
public/vendor/livewire/manifest.json
vendored
2
public/vendor/livewire/manifest.json
vendored
@@ -1,2 +1,2 @@
|
||||
|
||||
{"/livewire.js":"951e6947"}
|
||||
{"/livewire.js":"df3a17f2"}
|
||||
|
||||
@@ -973,10 +973,10 @@ label.form-control {
|
||||
|
||||
label.form-control--disabled {
|
||||
color: #959495;
|
||||
pointer-events:none;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
|
||||
/** --------------------------------------- **/
|
||||
/** Start checkbox styles to replace iCheck **/
|
||||
/** --------------------------------------- **/
|
||||
@@ -1165,6 +1165,11 @@ input[type="radio"]:checked::before {
|
||||
display: table-row !important;
|
||||
}
|
||||
|
||||
.form-control-static {
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
|
||||
td.text-right.text-padding-number-cell {
|
||||
padding-right: 30px !important;
|
||||
white-space: nowrap;
|
||||
|
||||
@@ -5,7 +5,7 @@ return [
|
||||
'manage' => 'crwdns6501:0crwdne6501:0',
|
||||
'field' => 'crwdns1487:0crwdne1487:0',
|
||||
'about_fieldsets_title' => 'crwdns1488:0crwdne1488:0',
|
||||
'about_fieldsets_text' => 'crwdns13464:0crwdne13464:0',
|
||||
'about_fieldsets_text' => 'crwdns13482:0crwdne13482:0',
|
||||
'custom_format' => 'crwdns6505:0crwdne6505:0',
|
||||
'encrypt_field' => 'crwdns1792:0crwdne1792:0',
|
||||
'encrypt_field_help' => 'crwdns1683:0crwdne1683:0',
|
||||
|
||||
@@ -55,7 +55,7 @@ return [
|
||||
'default_eula_text_placeholder' => 'crwdns13174:0crwdne13174:0',
|
||||
'default_language' => 'crwdns1581:0crwdne1581:0',
|
||||
'default_eula_help_text' => 'crwdns1260:0crwdne1260:0',
|
||||
'acceptance_note' => 'crwdns12186:0crwdne12186:0',
|
||||
'acceptance_note' => 'crwdns13488:0crwdne13488:0',
|
||||
'display_asset_name' => 'crwdns828:0crwdne828:0',
|
||||
'display_checkout_date' => 'crwdns829:0crwdne829:0',
|
||||
'display_eol' => 'crwdns1118:0crwdne1118:0',
|
||||
|
||||
@@ -14,5 +14,7 @@ return [
|
||||
'username_help_bottom' => 'crwdns6046:0crwdne6046:0',
|
||||
'google_login' => 'crwdns12026:0crwdne12026:0',
|
||||
'google_login_failed' => 'crwdns11603:0crwdne11603:0',
|
||||
'invite_password_expires' => 'crwdns13496:0crwdne13496:0',
|
||||
|
||||
];
|
||||
|
||||
|
||||
@@ -346,6 +346,8 @@ return [
|
||||
'audit_overdue' => 'crwdns5988:0crwdne5988:0',
|
||||
'accept' => 'crwdns6016:0crwdne6016:0',
|
||||
'i_accept' => 'crwdns6018:0crwdne6018:0',
|
||||
'i_decline_item' => 'crwdns13490:0crwdne13490:0',
|
||||
'i_accept_item' => 'crwdns13492:0crwdne13492:0',
|
||||
'i_decline' => 'crwdns6020:0crwdne6020:0',
|
||||
'accept_decline' => 'crwdns6163:0crwdne6163:0',
|
||||
'sign_tos' => 'crwdns6022:0crwdne6022:0',
|
||||
@@ -593,6 +595,7 @@ return [
|
||||
'version' => 'crwdns13278:0crwdne13278:0',
|
||||
'build' => 'crwdns13280:0crwdne13280:0',
|
||||
'footer_credit' => 'crwdns13282:0crwdne13282:0',
|
||||
'set_password' => 'crwdns13494:0crwdne13494:0',
|
||||
|
||||
// Add form placeholders here
|
||||
'placeholders' => [
|
||||
|
||||
@@ -8,11 +8,15 @@ return [
|
||||
'Asset_Checkout_Notification' => 'crwdns11625:0crwdne11625:0',
|
||||
'Confirm_Accessory_Checkin' => 'crwdns5992:0crwdne5992:0',
|
||||
'Confirm_Asset_Checkin' => 'crwdns5990:0crwdne5990:0',
|
||||
'Confirm_component_checkin' => 'crwdns13500:0crwdne13500:0',
|
||||
'Confirm_accessory_delivery' => 'crwdns5994:0crwdne5994:0',
|
||||
'Confirm_asset_delivery' => 'crwdns5998:0crwdne5998:0',
|
||||
'Confirm_consumable_delivery' => 'crwdns6000:0crwdne6000:0',
|
||||
'Confirm_component_delivery' => 'crwdns13502:0crwdne13502:0',
|
||||
'Confirm_license_delivery' => 'crwdns5996:0crwdne5996:0',
|
||||
'Consumable_checkout_notification' => 'crwdns12062:0crwdne12062:0',
|
||||
'Component_checkout_notification' => 'crwdns13504:0crwdne13504:0',
|
||||
'Component_checkin_notification' => 'crwdns13506:0crwdne13506:0',
|
||||
'Days' => 'crwdns1728:0crwdne1728:0',
|
||||
'Expected_Checkin_Date' => 'crwdns6012:0crwdne6012:0',
|
||||
'Expected_Checkin_Notification' => 'crwdns6030:0crwdne6030:0',
|
||||
@@ -33,7 +37,7 @@ return [
|
||||
'send_pdf_copy' => 'crwdns13480:0crwdne13480:0',
|
||||
'accessory_name' => 'crwdns12732:0crwdne12732:0',
|
||||
'additional_notes' => 'crwdns12734:0crwdne12734:0',
|
||||
'admin_has_created' => 'crwdns1708:0crwdne1708:0',
|
||||
'admin_has_created' => 'crwdns13498:0crwdne13498:0',
|
||||
'asset' => 'crwdns12750:0crwdne12750:0',
|
||||
'asset_name' => 'crwdns12716:0crwdne12716:0',
|
||||
'asset_requested' => 'crwdns1711:0crwdne1711:0',
|
||||
|
||||
@@ -5,7 +5,7 @@ return [
|
||||
'manage' => 'Manage',
|
||||
'field' => 'veld',
|
||||
'about_fieldsets_title' => 'Oor Fieldsets',
|
||||
'about_fieldsets_text' => 'Veldstelle stel jou in staat om groepe van persoonlike velde te skep wat gereeld hergebruik word vir spesifieke tipe bates.',
|
||||
'about_fieldsets_text' => 'Fieldsets allow you to create groups of custom fields that are frequently re-used for specific asset model types.',
|
||||
'custom_format' => 'Custom Regex format...',
|
||||
'encrypt_field' => 'Enkripteer die waarde van hierdie veld in die databasis',
|
||||
'encrypt_field_help' => 'WAARSKUWING: Om \'n veld te enkripteer, maak dit onondersoekbaar.',
|
||||
|
||||
@@ -55,7 +55,7 @@ return [
|
||||
'default_eula_text_placeholder' => 'Add your default EULA text',
|
||||
'default_language' => 'Verstek taal',
|
||||
'default_eula_help_text' => 'U kan ook aangepaste EULA\'s aan spesifieke batekategorieë assosieer.',
|
||||
'acceptance_note' => 'Add a note for your decision (Optional)',
|
||||
'acceptance_note' => 'Add a note for your decision (required if declining)',
|
||||
'display_asset_name' => 'Wys bate naam',
|
||||
'display_checkout_date' => 'Vertoon Checkout Date',
|
||||
'display_eol' => 'Wys EOL in tabelweergawe',
|
||||
|
||||
@@ -14,5 +14,7 @@ return [
|
||||
'username_help_bottom' => 'Your username and email address <em>may</em> be the same, but may not be, depending on your configuration. If you cannot remember your username, contact your administrator. <br><br><strong>Usernames without an associated email address will not be emailed a password reset link.</strong> ',
|
||||
'google_login' => 'Login with Google Workspace',
|
||||
'google_login_failed' => 'Google Login failed, please try again.',
|
||||
'invite_password_expires' => 'This password reset link will expire on :expire_date. You can use the manual password reset link to receive a new reset token by clicking here',
|
||||
|
||||
];
|
||||
|
||||
|
||||
@@ -346,6 +346,8 @@ return [
|
||||
'audit_overdue' => 'Overdue for Audit',
|
||||
'accept' => 'Accept :asset',
|
||||
'i_accept' => 'I accept',
|
||||
'i_decline_item' => 'Decline this item',
|
||||
'i_accept_item' => 'Accept this item',
|
||||
'i_decline' => 'I decline',
|
||||
'accept_decline' => 'Accept/Decline',
|
||||
'sign_tos' => 'Sign below to indicate that you agree to the terms of service:',
|
||||
@@ -594,6 +596,7 @@ return [
|
||||
'version' => 'Version',
|
||||
'build' => 'build',
|
||||
'footer_credit' => '<a target="_blank" href="https://snipeitapp.com" rel="noopener">Snipe-IT</a> is open source software, made with <i class="fa fa-heart" aria-hidden="true" style="color: #a94442; font-size: 10px" /></i><span class="sr-only">love</span> by <a href="https://bsky.app/profile/snipeitapp.com" rel="noopener">@snipeitapp.com</a>.',
|
||||
'set_password' => 'Set a Password',
|
||||
|
||||
// Add form placeholders here
|
||||
'placeholders' => [
|
||||
|
||||
@@ -8,11 +8,15 @@ return [
|
||||
'Asset_Checkout_Notification' => 'Asset checked out',
|
||||
'Confirm_Accessory_Checkin' => 'Accessory checkin confirmation',
|
||||
'Confirm_Asset_Checkin' => 'Asset checkin confirmation',
|
||||
'Confirm_component_checkin' => 'Component checkin confirmation',
|
||||
'Confirm_accessory_delivery' => 'Accessory delivery confirmation',
|
||||
'Confirm_asset_delivery' => 'Asset delivery confirmation',
|
||||
'Confirm_consumable_delivery' => 'Consumable delivery confirmation',
|
||||
'Confirm_component_delivery' => 'Component delivery confirmation',
|
||||
'Confirm_license_delivery' => 'License delivery confirmation',
|
||||
'Consumable_checkout_notification' => 'Consumable checked out',
|
||||
'Component_checkout_notification' => 'Component checked out',
|
||||
'Component_checkin_notification' => 'Component checked in',
|
||||
'Days' => 'dae',
|
||||
'Expected_Checkin_Date' => 'An asset checked out to you is due to be checked back in on :date',
|
||||
'Expected_Checkin_Notification' => 'Reminder: :name checkin deadline approaching',
|
||||
@@ -33,7 +37,7 @@ return [
|
||||
'send_pdf_copy' => 'Send a copy of this acceptance to my email address',
|
||||
'accessory_name' => 'Toebehore Naam',
|
||||
'additional_notes' => 'Bykomende aantekeninge',
|
||||
'admin_has_created' => '\'N Administrateur het \'n rekening vir jou op die webtuiste gemaak.',
|
||||
'admin_has_created' => 'An administrator has created an account for you on the :web website. Please find your username below, and click on the link to set a password.',
|
||||
'asset' => 'bate',
|
||||
'asset_name' => 'Bate Naam',
|
||||
'asset_requested' => 'Bate aangevra',
|
||||
|
||||
@@ -5,7 +5,7 @@ return [
|
||||
'manage' => 'Manage',
|
||||
'field' => 'Field',
|
||||
'about_fieldsets_title' => 'About Fieldsets',
|
||||
'about_fieldsets_text' => 'Fieldsets allow you to create groups of custom fields that are frequently re-used used for specific asset model types.',
|
||||
'about_fieldsets_text' => 'Fieldsets allow you to create groups of custom fields that are frequently re-used for specific asset model types.',
|
||||
'custom_format' => 'Custom Regex format...',
|
||||
'encrypt_field' => 'Encrypt the value of this field in the database',
|
||||
'encrypt_field_help' => 'WARNING: Encrypting a field makes it unsearchable.',
|
||||
|
||||
@@ -55,7 +55,7 @@ return [
|
||||
'default_eula_text_placeholder' => 'Add your default EULA text',
|
||||
'default_language' => 'Default Language',
|
||||
'default_eula_help_text' => 'You can also associate custom EULAs to specific asset categories.',
|
||||
'acceptance_note' => 'Add a note for your decision (Optional)',
|
||||
'acceptance_note' => 'Add a note for your decision (required if declining)',
|
||||
'display_asset_name' => 'Display Asset Name',
|
||||
'display_checkout_date' => 'Display Checkout Date',
|
||||
'display_eol' => 'Display EOL in table view',
|
||||
|
||||
@@ -14,5 +14,7 @@ return [
|
||||
'username_help_bottom' => 'Your username and email address <em>may</em> be the same, but may not be, depending on your configuration. If you cannot remember your username, contact your administrator. <br><br><strong>Usernames without an associated email address will not be emailed a password reset link.</strong> ',
|
||||
'google_login' => 'Login with Google Workspace',
|
||||
'google_login_failed' => 'Google Login failed, please try again.',
|
||||
'invite_password_expires' => 'This password reset link will expire on :expire_date. You can use the manual password reset link to receive a new reset token by clicking here',
|
||||
|
||||
];
|
||||
|
||||
|
||||
@@ -346,6 +346,8 @@ return [
|
||||
'audit_overdue' => 'Overdue for Audit',
|
||||
'accept' => 'Accept :asset',
|
||||
'i_accept' => 'I accept',
|
||||
'i_decline_item' => 'Decline this item',
|
||||
'i_accept_item' => 'Accept this item',
|
||||
'i_decline' => 'I decline',
|
||||
'accept_decline' => 'Accept/Decline',
|
||||
'sign_tos' => 'Sign below to indicate that you agree to the terms of service:',
|
||||
@@ -594,6 +596,7 @@ return [
|
||||
'version' => 'Version',
|
||||
'build' => 'build',
|
||||
'footer_credit' => '<a target="_blank" href="https://snipeitapp.com" rel="noopener">Snipe-IT</a> is open source software, made with <i class="fa fa-heart" aria-hidden="true" style="color: #a94442; font-size: 10px" /></i><span class="sr-only">love</span> by <a href="https://bsky.app/profile/snipeitapp.com" rel="noopener">@snipeitapp.com</a>.',
|
||||
'set_password' => 'Set a Password',
|
||||
|
||||
// Add form placeholders here
|
||||
'placeholders' => [
|
||||
|
||||
@@ -8,11 +8,15 @@ return [
|
||||
'Asset_Checkout_Notification' => 'Asset checked out',
|
||||
'Confirm_Accessory_Checkin' => 'Accessory checkin confirmation',
|
||||
'Confirm_Asset_Checkin' => 'Asset checkin confirmation',
|
||||
'Confirm_component_checkin' => 'Component checkin confirmation',
|
||||
'Confirm_accessory_delivery' => 'Accessory delivery confirmation',
|
||||
'Confirm_asset_delivery' => 'Asset delivery confirmation',
|
||||
'Confirm_consumable_delivery' => 'Consumable delivery confirmation',
|
||||
'Confirm_component_delivery' => 'Component delivery confirmation',
|
||||
'Confirm_license_delivery' => 'License delivery confirmation',
|
||||
'Consumable_checkout_notification' => 'Consumable checked out',
|
||||
'Component_checkout_notification' => 'Component checked out',
|
||||
'Component_checkin_notification' => 'Component checked in',
|
||||
'Days' => 'Days',
|
||||
'Expected_Checkin_Date' => 'An asset checked out to you is due to be checked back in on :date',
|
||||
'Expected_Checkin_Notification' => 'Reminder: :name checkin deadline approaching',
|
||||
@@ -33,7 +37,7 @@ return [
|
||||
'send_pdf_copy' => 'Send a copy of this acceptance to my email address',
|
||||
'accessory_name' => 'Accessory Name',
|
||||
'additional_notes' => 'Additional Notes',
|
||||
'admin_has_created' => 'An administrator has created an account for you on the :web website.',
|
||||
'admin_has_created' => 'An administrator has created an account for you on the :web website. Please find your username below, and click on the link to set a password.',
|
||||
'asset' => 'ንብረት',
|
||||
'asset_name' => 'Asset Name',
|
||||
'asset_requested' => 'Asset requested',
|
||||
|
||||
@@ -5,7 +5,7 @@ return [
|
||||
'manage' => 'إدارة',
|
||||
'field' => 'حقل',
|
||||
'about_fieldsets_title' => 'حول مجموعة الحقول',
|
||||
'about_fieldsets_text' => '(مجموعات الحقول) تسمح لك بإنشاء مجموعات من الحقول اللتي يمكن إعادة إستخدامها مع موديل محدد.',
|
||||
'about_fieldsets_text' => 'مجموعات الحقول تسمح لك بإنشاء مجموعات من الحقول المخصصة التي يعاد استخدامها في كثير من الأحيان لأنواع معينة من نماذج الأصول.',
|
||||
'custom_format' => 'تنسيق Regex المخصص...',
|
||||
'encrypt_field' => 'تشفير قيمة هذا الحقل في قاعدة البيانات',
|
||||
'encrypt_field_help' => 'تحذير: تشفير الحقل يجعله غير قابل للبحث.',
|
||||
|
||||
@@ -55,7 +55,7 @@ return [
|
||||
'default_eula_text_placeholder' => 'Add your default EULA text',
|
||||
'default_language' => 'اللغة الافتراضية',
|
||||
'default_eula_help_text' => 'يمكنك أيضا ربط (اتفاقية ترخيص المستخدم) لاصناف محددة من الاصول.',
|
||||
'acceptance_note' => 'Add a note for your decision (Optional)',
|
||||
'acceptance_note' => 'Add a note for your decision (required if declining)',
|
||||
'display_asset_name' => 'عرض اسم مادة العرض',
|
||||
'display_checkout_date' => 'عرض تاريخ الخروج',
|
||||
'display_eol' => 'عرض نهاية العمر على شكل جدول',
|
||||
|
||||
@@ -14,5 +14,7 @@ return [
|
||||
'username_help_bottom' => 'قد يكون اسم المستخدم وعنوان البريد الإلكتروني الخاصين بك متماثلين، ولكن قد لا يكونا كذلك، بناءً على الإعدادات الخاصة بك. إذا كنت لا تستطيع تذكر اسم المستخدم الخاص بك، اتصل بالمسؤول. لن يتم إرسال رابط إعادة تعيين كلمة المرور عبر البريد الإلكتروني إلى أسماء المستخدمين التي لا تحتوي على عنوان بريد إلكتروني مرتبط بها ',
|
||||
'google_login' => 'تسجيل الدخول باستخدام مساحة عمل جوجل',
|
||||
'google_login_failed' => 'فشل تسجيل دخول جوجل، الرجاء المحاولة مرة أخرى.',
|
||||
'invite_password_expires' => 'This password reset link will expire on :expire_date. You can use the manual password reset link to receive a new reset token by clicking here',
|
||||
|
||||
];
|
||||
|
||||
|
||||
@@ -346,6 +346,8 @@ return [
|
||||
'audit_overdue' => 'مراجعة الحسابات المتأخرة',
|
||||
'accept' => 'قبول :asset',
|
||||
'i_accept' => 'قبول',
|
||||
'i_decline_item' => 'Decline this item',
|
||||
'i_accept_item' => 'Accept this item',
|
||||
'i_decline' => 'أنا أرفض',
|
||||
'accept_decline' => 'قبول/رفض',
|
||||
'sign_tos' => 'قم بتسجيل الدخول أدناه للإشارة إلى أنك توافق على شروط الخدمة:',
|
||||
@@ -594,6 +596,7 @@ return [
|
||||
'version' => 'Version',
|
||||
'build' => 'build',
|
||||
'footer_credit' => '<a target="_blank" href="https://snipeitapp.com" rel="noopener">Snipe-IT</a> is open source software, made with <i class="fa fa-heart" aria-hidden="true" style="color: #a94442; font-size: 10px" /></i><span class="sr-only">love</span> by <a href="https://bsky.app/profile/snipeitapp.com" rel="noopener">@snipeitapp.com</a>.',
|
||||
'set_password' => 'Set a Password',
|
||||
|
||||
// Add form placeholders here
|
||||
'placeholders' => [
|
||||
|
||||
@@ -8,11 +8,15 @@ return [
|
||||
'Asset_Checkout_Notification' => 'تم إخراج الأصل',
|
||||
'Confirm_Accessory_Checkin' => 'تأكيد تسجيل الأصول',
|
||||
'Confirm_Asset_Checkin' => 'تأكيد تسجيل الأصول',
|
||||
'Confirm_component_checkin' => 'Component checkin confirmation',
|
||||
'Confirm_accessory_delivery' => 'تأكيد توصيل الأصول',
|
||||
'Confirm_asset_delivery' => 'تأكيد تسليم الأصول',
|
||||
'Confirm_consumable_delivery' => 'تأكيد التسليم المستهلكة',
|
||||
'Confirm_component_delivery' => 'Component delivery confirmation',
|
||||
'Confirm_license_delivery' => 'تأكيد توصيل الرخصة',
|
||||
'Consumable_checkout_notification' => 'تم فحص المواد المستهلكة',
|
||||
'Component_checkout_notification' => 'Component checked out',
|
||||
'Component_checkin_notification' => 'Component checked in',
|
||||
'Days' => 'أيام',
|
||||
'Expected_Checkin_Date' => 'من المقرر أن يتم التحقق من الأصول التي تم إخراجها إليك في :date',
|
||||
'Expected_Checkin_Notification' => 'تذكير: تاريخ تحقق :name يقترب من الموعد النهائي',
|
||||
@@ -33,7 +37,7 @@ return [
|
||||
'send_pdf_copy' => 'Send a copy of this acceptance to my email address',
|
||||
'accessory_name' => 'اسم الملحق',
|
||||
'additional_notes' => 'ملاحظات إضافية',
|
||||
'admin_has_created' => 'قام مسؤول بإنشاء حساب لك على الموقع :web.',
|
||||
'admin_has_created' => 'An administrator has created an account for you on the :web website. Please find your username below, and click on the link to set a password.',
|
||||
'asset' => 'أصل',
|
||||
'asset_name' => 'اسم الأصل',
|
||||
'asset_requested' => 'تم طلب مادة العرض',
|
||||
|
||||
@@ -5,7 +5,7 @@ return [
|
||||
'manage' => 'Управление',
|
||||
'field' => 'Поле',
|
||||
'about_fieldsets_title' => 'Относно Fieldsets',
|
||||
'about_fieldsets_text' => 'Fieldsets позволяват създаването на групи от персонализирани полета, които се използват и преизползват често за специфични типове модели на активи.',
|
||||
'about_fieldsets_text' => '"Група от полета" позволяват създаването на групи от персонализирани полета, които се използват и преизползват често за специфични типове модели на активи.',
|
||||
'custom_format' => 'Персонализиран формат...',
|
||||
'encrypt_field' => 'Шифроване на стойността на това поле в базата данни',
|
||||
'encrypt_field_help' => 'ВНИМАНИЕ: Шифроване на поле го прави невалидно за търсене.',
|
||||
|
||||
@@ -55,7 +55,7 @@ return [
|
||||
'default_eula_text_placeholder' => 'Добавете ваш EULA',
|
||||
'default_language' => 'Език по подразбиране',
|
||||
'default_eula_help_text' => 'Можете да асоциирате специфична EULA към всяка избрана категория.',
|
||||
'acceptance_note' => 'Добавете бележка за вашето решение (По желание)',
|
||||
'acceptance_note' => 'Add a note for your decision (required if declining)',
|
||||
'display_asset_name' => 'Визуализиране на актив',
|
||||
'display_checkout_date' => 'Визуализиране на дата на изписване',
|
||||
'display_eol' => 'Визуализиране на EOL в таблиците',
|
||||
|
||||
@@ -14,5 +14,7 @@ return [
|
||||
'username_help_bottom' => 'Вашето потребителско име и е-майл адрес <em>може да</em> са еднакви или да не са, зависимост от вашата конфигурация. Ако не помните вашето потребителско име се свържете с Администратора. <br><br><strong>Потребители които нямат въведен е-майл адрес няма да получат линк за смяна на парола.</strong> ',
|
||||
'google_login' => 'Вход с Google Workspace',
|
||||
'google_login_failed' => 'Неуспешен вход с Google Login, пробвайте отново.',
|
||||
'invite_password_expires' => 'This password reset link will expire on :expire_date. You can use the manual password reset link to receive a new reset token by clicking here',
|
||||
|
||||
];
|
||||
|
||||
|
||||
@@ -346,6 +346,8 @@ return [
|
||||
'audit_overdue' => 'Просрочен Одит',
|
||||
'accept' => 'Приеми :asset',
|
||||
'i_accept' => 'Съгласен съм',
|
||||
'i_decline_item' => 'Decline this item',
|
||||
'i_accept_item' => 'Accept this item',
|
||||
'i_decline' => 'Отказ',
|
||||
'accept_decline' => 'Премане/отказване',
|
||||
'sign_tos' => 'Подпишете се за да се съгласите с условията за ползване:',
|
||||
@@ -594,6 +596,7 @@ return [
|
||||
'version' => 'Version',
|
||||
'build' => 'build',
|
||||
'footer_credit' => '<a target="_blank" href="https://snipeitapp.com" rel="noopener">Snipe-IT</a> is open source software, made with <i class="fa fa-heart" aria-hidden="true" style="color: #a94442; font-size: 10px" /></i><span class="sr-only">love</span> by <a href="https://bsky.app/profile/snipeitapp.com" rel="noopener">@snipeitapp.com</a>.',
|
||||
'set_password' => 'Set a Password',
|
||||
|
||||
// Add form placeholders here
|
||||
'placeholders' => [
|
||||
|
||||
@@ -8,11 +8,15 @@ return [
|
||||
'Asset_Checkout_Notification' => 'Актива е изписан',
|
||||
'Confirm_Accessory_Checkin' => 'Потвърждение при връщане на аксесоар',
|
||||
'Confirm_Asset_Checkin' => 'Потвърждение при връщане на актив',
|
||||
'Confirm_component_checkin' => 'Component checkin confirmation',
|
||||
'Confirm_accessory_delivery' => 'Потвърждение при доставка на аксесоар',
|
||||
'Confirm_asset_delivery' => 'Потвърждение при доставка на актив',
|
||||
'Confirm_consumable_delivery' => 'Потвърждение при доставка на консуматив',
|
||||
'Confirm_component_delivery' => 'Component delivery confirmation',
|
||||
'Confirm_license_delivery' => 'Потвърждение при доставка на лиценз',
|
||||
'Consumable_checkout_notification' => 'Изписани консумативи',
|
||||
'Component_checkout_notification' => 'Component checked out',
|
||||
'Component_checkin_notification' => 'Component checked in',
|
||||
'Days' => 'Дни',
|
||||
'Expected_Checkin_Date' => 'Наближава срока за връщане на актив който е заведен на Вас, трябва да се върна на :date',
|
||||
'Expected_Checkin_Notification' => 'Напомняне: :name крайната дата за вписване наближава',
|
||||
@@ -33,7 +37,7 @@ return [
|
||||
'send_pdf_copy' => 'Send a copy of this acceptance to my email address',
|
||||
'accessory_name' => 'Аксесоар',
|
||||
'additional_notes' => 'Допълнителни бележки',
|
||||
'admin_has_created' => 'Администратор е създал акаунт за вас на :web website.',
|
||||
'admin_has_created' => 'An administrator has created an account for you on the :web website. Please find your username below, and click on the link to set a password.',
|
||||
'asset' => 'Актив',
|
||||
'asset_name' => 'Име на актив',
|
||||
'asset_requested' => 'Заявка за актив',
|
||||
|
||||
@@ -5,7 +5,7 @@ return [
|
||||
'manage' => 'Manage',
|
||||
'field' => 'Field',
|
||||
'about_fieldsets_title' => 'About Fieldsets',
|
||||
'about_fieldsets_text' => 'Fieldsets allow you to create groups of custom fields that are frequently re-used used for specific asset model types.',
|
||||
'about_fieldsets_text' => 'Fieldsets allow you to create groups of custom fields that are frequently re-used for specific asset model types.',
|
||||
'custom_format' => 'Custom Regex format...',
|
||||
'encrypt_field' => 'Encrypt the value of this field in the database',
|
||||
'encrypt_field_help' => 'WARNING: Encrypting a field makes it unsearchable.',
|
||||
|
||||
@@ -55,7 +55,7 @@ return [
|
||||
'default_eula_text_placeholder' => 'Add your default EULA text',
|
||||
'default_language' => 'Default Language',
|
||||
'default_eula_help_text' => 'You can also associate custom EULAs to specific asset categories.',
|
||||
'acceptance_note' => 'Add a note for your decision (Optional)',
|
||||
'acceptance_note' => 'Add a note for your decision (required if declining)',
|
||||
'display_asset_name' => 'Display Asset Name',
|
||||
'display_checkout_date' => 'Display Checkout Date',
|
||||
'display_eol' => 'Display EOL in table view',
|
||||
|
||||
@@ -14,5 +14,7 @@ return [
|
||||
'username_help_bottom' => 'Your username and email address <em>may</em> be the same, but may not be, depending on your configuration. If you cannot remember your username, contact your administrator. <br><br><strong>Usernames without an associated email address will not be emailed a password reset link.</strong> ',
|
||||
'google_login' => 'Login with Google Workspace',
|
||||
'google_login_failed' => 'Google Login failed, please try again.',
|
||||
'invite_password_expires' => 'This password reset link will expire on :expire_date. You can use the manual password reset link to receive a new reset token by clicking here',
|
||||
|
||||
];
|
||||
|
||||
|
||||
@@ -346,6 +346,8 @@ return [
|
||||
'audit_overdue' => 'Overdue for Audit',
|
||||
'accept' => 'Acceptar :recurs',
|
||||
'i_accept' => 'I accept',
|
||||
'i_decline_item' => 'Decline this item',
|
||||
'i_accept_item' => 'Accept this item',
|
||||
'i_decline' => 'I decline',
|
||||
'accept_decline' => 'Accept/Decline',
|
||||
'sign_tos' => 'Sign below to indicate that you agree to the terms of service:',
|
||||
@@ -594,6 +596,7 @@ return [
|
||||
'version' => 'Version',
|
||||
'build' => 'build',
|
||||
'footer_credit' => '<a target="_blank" href="https://snipeitapp.com" rel="noopener">Snipe-IT</a> is open source software, made with <i class="fa fa-heart" aria-hidden="true" style="color: #a94442; font-size: 10px" /></i><span class="sr-only">love</span> by <a href="https://bsky.app/profile/snipeitapp.com" rel="noopener">@snipeitapp.com</a>.',
|
||||
'set_password' => 'Set a Password',
|
||||
|
||||
// Add form placeholders here
|
||||
'placeholders' => [
|
||||
|
||||
@@ -8,11 +8,15 @@ return [
|
||||
'Asset_Checkout_Notification' => 'Asset checked out',
|
||||
'Confirm_Accessory_Checkin' => 'Accessory checkin confirmation',
|
||||
'Confirm_Asset_Checkin' => 'Asset checkin confirmation',
|
||||
'Confirm_component_checkin' => 'Component checkin confirmation',
|
||||
'Confirm_accessory_delivery' => 'Accessory delivery confirmation',
|
||||
'Confirm_asset_delivery' => 'Asset delivery confirmation',
|
||||
'Confirm_consumable_delivery' => 'Consumable delivery confirmation',
|
||||
'Confirm_component_delivery' => 'Component delivery confirmation',
|
||||
'Confirm_license_delivery' => 'License delivery confirmation',
|
||||
'Consumable_checkout_notification' => 'Consumable checked out',
|
||||
'Component_checkout_notification' => 'Component checked out',
|
||||
'Component_checkin_notification' => 'Component checked in',
|
||||
'Days' => 'Days',
|
||||
'Expected_Checkin_Date' => 'An asset checked out to you is due to be checked back in on :date',
|
||||
'Expected_Checkin_Notification' => 'Reminder: :name checkin deadline approaching',
|
||||
@@ -33,7 +37,7 @@ return [
|
||||
'send_pdf_copy' => 'Send a copy of this acceptance to my email address',
|
||||
'accessory_name' => 'Accessory Name',
|
||||
'additional_notes' => 'Additional Notes',
|
||||
'admin_has_created' => 'An administrator has created an account for you on the :web website.',
|
||||
'admin_has_created' => 'An administrator has created an account for you on the :web website. Please find your username below, and click on the link to set a password.',
|
||||
'asset' => 'Recurs',
|
||||
'asset_name' => 'Asset Name',
|
||||
'asset_requested' => 'Asset requested',
|
||||
|
||||
@@ -5,7 +5,7 @@ return [
|
||||
'manage' => 'Manage',
|
||||
'field' => 'Field',
|
||||
'about_fieldsets_title' => 'About Fieldsets',
|
||||
'about_fieldsets_text' => 'Fieldsets allow you to create groups of custom fields that are frequently re-used used for specific asset model types.',
|
||||
'about_fieldsets_text' => 'Fieldsets allow you to create groups of custom fields that are frequently re-used for specific asset model types.',
|
||||
'custom_format' => 'Custom Regex format...',
|
||||
'encrypt_field' => 'Encrypt the value of this field in the database',
|
||||
'encrypt_field_help' => 'WARNING: Encrypting a field makes it unsearchable.',
|
||||
|
||||
@@ -55,7 +55,7 @@ return [
|
||||
'default_eula_text_placeholder' => 'Add your default EULA text',
|
||||
'default_language' => 'Default Language',
|
||||
'default_eula_help_text' => 'You can also associate custom EULAs to specific asset categories.',
|
||||
'acceptance_note' => 'Add a note for your decision (Optional)',
|
||||
'acceptance_note' => 'Add a note for your decision (required if declining)',
|
||||
'display_asset_name' => 'Display Asset Name',
|
||||
'display_checkout_date' => 'Display Checkout Date',
|
||||
'display_eol' => 'Display EOL in table view',
|
||||
|
||||
@@ -14,5 +14,7 @@ return [
|
||||
'username_help_bottom' => 'Your username and email address <em>may</em> be the same, but may not be, depending on your configuration. If you cannot remember your username, contact your administrator. <br><br><strong>Usernames without an associated email address will not be emailed a password reset link.</strong> ',
|
||||
'google_login' => 'Login with Google Workspace',
|
||||
'google_login_failed' => 'Google Login failed, please try again.',
|
||||
'invite_password_expires' => 'This password reset link will expire on :expire_date. You can use the manual password reset link to receive a new reset token by clicking here',
|
||||
|
||||
];
|
||||
|
||||
|
||||
@@ -346,6 +346,8 @@ return [
|
||||
'audit_overdue' => 'Overdue for Audit',
|
||||
'accept' => 'Accept :asset',
|
||||
'i_accept' => 'I accept',
|
||||
'i_decline_item' => 'Decline this item',
|
||||
'i_accept_item' => 'Accept this item',
|
||||
'i_decline' => 'I decline',
|
||||
'accept_decline' => 'Accept/Decline',
|
||||
'sign_tos' => 'Sign below to indicate that you agree to the terms of service:',
|
||||
@@ -594,6 +596,7 @@ return [
|
||||
'version' => 'Version',
|
||||
'build' => 'build',
|
||||
'footer_credit' => '<a target="_blank" href="https://snipeitapp.com" rel="noopener">Snipe-IT</a> is open source software, made with <i class="fa fa-heart" aria-hidden="true" style="color: #a94442; font-size: 10px" /></i><span class="sr-only">love</span> by <a href="https://bsky.app/profile/snipeitapp.com" rel="noopener">@snipeitapp.com</a>.',
|
||||
'set_password' => 'Set a Password',
|
||||
|
||||
// Add form placeholders here
|
||||
'placeholders' => [
|
||||
|
||||
@@ -8,11 +8,15 @@ return [
|
||||
'Asset_Checkout_Notification' => 'Asset checked out',
|
||||
'Confirm_Accessory_Checkin' => 'Accessory checkin confirmation',
|
||||
'Confirm_Asset_Checkin' => 'Asset checkin confirmation',
|
||||
'Confirm_component_checkin' => 'Component checkin confirmation',
|
||||
'Confirm_accessory_delivery' => 'Accessory delivery confirmation',
|
||||
'Confirm_asset_delivery' => 'Asset delivery confirmation',
|
||||
'Confirm_consumable_delivery' => 'Consumable delivery confirmation',
|
||||
'Confirm_component_delivery' => 'Component delivery confirmation',
|
||||
'Confirm_license_delivery' => 'License delivery confirmation',
|
||||
'Consumable_checkout_notification' => 'Consumable checked out',
|
||||
'Component_checkout_notification' => 'Component checked out',
|
||||
'Component_checkin_notification' => 'Component checked in',
|
||||
'Days' => 'Days',
|
||||
'Expected_Checkin_Date' => 'An asset checked out to you is due to be checked back in on :date',
|
||||
'Expected_Checkin_Notification' => 'Reminder: :name checkin deadline approaching',
|
||||
@@ -33,7 +37,7 @@ return [
|
||||
'send_pdf_copy' => 'Send a copy of this acceptance to my email address',
|
||||
'accessory_name' => 'Accessory Name',
|
||||
'additional_notes' => 'Additional Notes',
|
||||
'admin_has_created' => 'An administrator has created an account for you on the :web website.',
|
||||
'admin_has_created' => 'An administrator has created an account for you on the :web website. Please find your username below, and click on the link to set a password.',
|
||||
'asset' => 'Asset',
|
||||
'asset_name' => 'Asset Name',
|
||||
'asset_requested' => 'Asset requested',
|
||||
|
||||
@@ -57,7 +57,7 @@ return [
|
||||
'default_eula_text_placeholder' => 'Přidat výchozí text EULA',
|
||||
'default_language' => 'Výchozí jazyk',
|
||||
'default_eula_help_text' => 'Můžete také spojit vlastní EULA se specifickými kategoriemi majetku.',
|
||||
'acceptance_note' => 'Přidat poznámku k vašemu rozhodnutí (nepovinné)',
|
||||
'acceptance_note' => 'Add a note for your decision (required if declining)',
|
||||
'display_asset_name' => 'Zobrazit název majetku',
|
||||
'display_checkout_date' => 'Zobrazit den převzetí',
|
||||
'display_eol' => 'Zobrazit EOL v tabulkovém zobrazení',
|
||||
|
||||
@@ -14,5 +14,7 @@ return [
|
||||
'username_help_bottom' => 'Vaše uživatelské jméno a e-mailová adresa <em>mohou</em> být stejná, ale nemusí být, záleží na Vašem nastavení. Pokud si nepamatujete Vaše uživatelské jméno, kontaktujte Vašeho správce. <br><br><strong>Uživatelským jménům bez přidružené e-mailové adresy nebude zaslán odkaz pro obnovu hesla.</strong> ',
|
||||
'google_login' => 'Přihlásit se pomocí Google Workspace',
|
||||
'google_login_failed' => 'Přihlášení Google se nezdařilo, zkuste to prosím znovu.',
|
||||
'invite_password_expires' => 'This password reset link will expire on :expire_date. You can use the manual password reset link to receive a new reset token by clicking here',
|
||||
|
||||
];
|
||||
|
||||
|
||||
@@ -346,6 +346,8 @@ return [
|
||||
'audit_overdue' => 'Po termínu inventury',
|
||||
'accept' => 'Přijmout :asset',
|
||||
'i_accept' => 'Přijímám',
|
||||
'i_decline_item' => 'Decline this item',
|
||||
'i_accept_item' => 'Accept this item',
|
||||
'i_decline' => 'Odmítám',
|
||||
'accept_decline' => 'Přijímat/zamítnout',
|
||||
'sign_tos' => 'Podepsáním níže souhlasíte s podmínkami služby:',
|
||||
@@ -596,6 +598,7 @@ return [
|
||||
'version' => 'Verze',
|
||||
'build' => 'sestavení',
|
||||
'footer_credit' => '<a target="_blank" href="https://snipeitapp.com" rel="noopener">Snipe-IT</a> Je open-source software, vytvořený s <i class="fa fa-heart" aria-hidden="true" style="color: #a94442; font-size: 10px" /></i><span class="sr-only">láskou</span> od <a href="https://bsky.app/profile/snipeitapp.com" rel="noopener">@snipeitapp.com</a>.',
|
||||
'set_password' => 'Set a Password',
|
||||
|
||||
// Add form placeholders here
|
||||
'placeholders' => [
|
||||
|
||||
@@ -8,11 +8,15 @@ return [
|
||||
'Asset_Checkout_Notification' => 'Majetek zkontrolován',
|
||||
'Confirm_Accessory_Checkin' => 'Potvrzení odevzdání příslušenství',
|
||||
'Confirm_Asset_Checkin' => 'Potvrzení odevzdání předmětu',
|
||||
'Confirm_component_checkin' => 'Component checkin confirmation',
|
||||
'Confirm_accessory_delivery' => 'Potvrďte dodání příslušenství',
|
||||
'Confirm_asset_delivery' => 'Potvrďte dodání majetku',
|
||||
'Confirm_consumable_delivery' => 'Potvrďte dodání spotřebního zboží',
|
||||
'Confirm_component_delivery' => 'Component delivery confirmation',
|
||||
'Confirm_license_delivery' => 'Potvrdit dodání licence',
|
||||
'Consumable_checkout_notification' => 'Spotřební materiál byl zkontrolován',
|
||||
'Component_checkout_notification' => 'Component checked out',
|
||||
'Component_checkin_notification' => 'Component checked in',
|
||||
'Days' => 'Dní',
|
||||
'Expected_Checkin_Date' => 'Majetek, který vám byl předán, musí být vrácen zpět do :date',
|
||||
'Expected_Checkin_Notification' => 'Připomenutí: blížící se lhůta pro :name',
|
||||
@@ -33,7 +37,7 @@ return [
|
||||
'send_pdf_copy' => 'Send a copy of this acceptance to my email address',
|
||||
'accessory_name' => 'Název příslušenství',
|
||||
'additional_notes' => 'Další Poznámky',
|
||||
'admin_has_created' => 'Administrátor pro vás vytvořil účet na stránce :web.',
|
||||
'admin_has_created' => 'An administrator has created an account for you on the :web website. Please find your username below, and click on the link to set a password.',
|
||||
'asset' => 'Majetek',
|
||||
'asset_name' => 'Název majetku',
|
||||
'asset_requested' => 'Požadovaný majetek',
|
||||
|
||||
@@ -5,7 +5,7 @@ return [
|
||||
'manage' => 'Manage',
|
||||
'field' => 'Meysydd',
|
||||
'about_fieldsets_title' => 'Amdan grwpiau meysydd',
|
||||
'about_fieldsets_text' => 'Mae grwpiau meysydd yn caniatau i chi creu grwpiau o meysydd addasedig sydd yn cael ei defnyddio yn amal ar gyfer mathau penodol o asedau.',
|
||||
'about_fieldsets_text' => 'Fieldsets allow you to create groups of custom fields that are frequently re-used for specific asset model types.',
|
||||
'custom_format' => 'Custom Regex format...',
|
||||
'encrypt_field' => 'Hamcryptio gwerth y maes yma yn y basdata',
|
||||
'encrypt_field_help' => 'RHYBUDD: Mae hamcryptio maes yn feddwl nid oes modd chwilio amdano.',
|
||||
|
||||
@@ -55,7 +55,7 @@ return [
|
||||
'default_eula_text_placeholder' => 'Add your default EULA text',
|
||||
'default_language' => 'Iaith Diofyn',
|
||||
'default_eula_help_text' => 'Yn ogystal, fedrwch perthnasu CTDT yn erbyn asedau penodol.',
|
||||
'acceptance_note' => 'Add a note for your decision (Optional)',
|
||||
'acceptance_note' => 'Add a note for your decision (required if declining)',
|
||||
'display_asset_name' => 'Dangos Enw Ased',
|
||||
'display_checkout_date' => 'Dangos Dyddiad Allan',
|
||||
'display_eol' => 'Dangos DB yn y tabl',
|
||||
|
||||
@@ -14,5 +14,7 @@ return [
|
||||
'username_help_bottom' => 'Your username and email address <em>may</em> be the same, but may not be, depending on your configuration. If you cannot remember your username, contact your administrator. <br><br><strong>Usernames without an associated email address will not be emailed a password reset link.</strong> ',
|
||||
'google_login' => 'Login with Google Workspace',
|
||||
'google_login_failed' => 'Google Login failed, please try again.',
|
||||
'invite_password_expires' => 'This password reset link will expire on :expire_date. You can use the manual password reset link to receive a new reset token by clicking here',
|
||||
|
||||
];
|
||||
|
||||
|
||||
@@ -346,6 +346,8 @@ return [
|
||||
'audit_overdue' => 'Overdue for Audit',
|
||||
'accept' => 'Accept :asset',
|
||||
'i_accept' => 'I accept',
|
||||
'i_decline_item' => 'Decline this item',
|
||||
'i_accept_item' => 'Accept this item',
|
||||
'i_decline' => 'I decline',
|
||||
'accept_decline' => 'Accept/Decline',
|
||||
'sign_tos' => 'Sign below to indicate that you agree to the terms of service:',
|
||||
@@ -594,6 +596,7 @@ return [
|
||||
'version' => 'Version',
|
||||
'build' => 'build',
|
||||
'footer_credit' => '<a target="_blank" href="https://snipeitapp.com" rel="noopener">Snipe-IT</a> is open source software, made with <i class="fa fa-heart" aria-hidden="true" style="color: #a94442; font-size: 10px" /></i><span class="sr-only">love</span> by <a href="https://bsky.app/profile/snipeitapp.com" rel="noopener">@snipeitapp.com</a>.',
|
||||
'set_password' => 'Set a Password',
|
||||
|
||||
// Add form placeholders here
|
||||
'placeholders' => [
|
||||
|
||||
@@ -8,11 +8,15 @@ return [
|
||||
'Asset_Checkout_Notification' => 'Asset checked out',
|
||||
'Confirm_Accessory_Checkin' => 'Accessory checkin confirmation',
|
||||
'Confirm_Asset_Checkin' => 'Asset checkin confirmation',
|
||||
'Confirm_component_checkin' => 'Component checkin confirmation',
|
||||
'Confirm_accessory_delivery' => 'Accessory delivery confirmation',
|
||||
'Confirm_asset_delivery' => 'Asset delivery confirmation',
|
||||
'Confirm_consumable_delivery' => 'Consumable delivery confirmation',
|
||||
'Confirm_component_delivery' => 'Component delivery confirmation',
|
||||
'Confirm_license_delivery' => 'License delivery confirmation',
|
||||
'Consumable_checkout_notification' => 'Consumable checked out',
|
||||
'Component_checkout_notification' => 'Component checked out',
|
||||
'Component_checkin_notification' => 'Component checked in',
|
||||
'Days' => 'Dyddiau',
|
||||
'Expected_Checkin_Date' => 'An asset checked out to you is due to be checked back in on :date',
|
||||
'Expected_Checkin_Notification' => 'Reminder: :name checkin deadline approaching',
|
||||
@@ -33,7 +37,7 @@ return [
|
||||
'send_pdf_copy' => 'Send a copy of this acceptance to my email address',
|
||||
'accessory_name' => 'Enw Ategolyn',
|
||||
'additional_notes' => 'Nodiadau ychwanegol',
|
||||
'admin_has_created' => 'Mae gweinyddwr wedi creu cyfrif i chi a yr :web wefan.',
|
||||
'admin_has_created' => 'An administrator has created an account for you on the :web website. Please find your username below, and click on the link to set a password.',
|
||||
'asset' => 'Ased',
|
||||
'asset_name' => 'Enw Ased',
|
||||
'asset_requested' => 'Gofynnwyd am ased',
|
||||
|
||||
@@ -5,7 +5,7 @@ return [
|
||||
'manage' => 'Administrer',
|
||||
'field' => 'Felt',
|
||||
'about_fieldsets_title' => 'Om Feltsæt',
|
||||
'about_fieldsets_text' => 'Fieldsets giver dig mulighed for at oprette grupper af brugerdefinerede felter, der ofte bruges igen til specifikke aktivmodeltyper.',
|
||||
'about_fieldsets_text' => 'Feltsæt giver dig mulighed for at oprette grupper af brugerdefinerede felter, der ofte genbruges til specifikke asset-modeltyper.',
|
||||
'custom_format' => 'Tilpasset Regex format...',
|
||||
'encrypt_field' => 'Kryptere værdien af dette felt i databasen',
|
||||
'encrypt_field_help' => 'Advarsel: Kryptere et felt gør det uransagelige.',
|
||||
|
||||
@@ -55,7 +55,7 @@ return [
|
||||
'default_eula_text_placeholder' => 'Add your default EULA text',
|
||||
'default_language' => 'Standard sprog',
|
||||
'default_eula_help_text' => 'Du kan også knytte brugerdefinerede EULA til specifikke aktivkategorier.',
|
||||
'acceptance_note' => 'Add a note for your decision (Optional)',
|
||||
'acceptance_note' => 'Add a note for your decision (required if declining)',
|
||||
'display_asset_name' => 'Vis aktivnavn',
|
||||
'display_checkout_date' => 'Vis checkout dato',
|
||||
'display_eol' => 'Vis EOL i tabelvisning',
|
||||
|
||||
@@ -14,5 +14,7 @@ return [
|
||||
'username_help_bottom' => 'Dit brugernavn og din emailadresse <em>kan</em> være den samme; men din konfiguration kan kæve at de er forskellige. Hvis du ikke kan huske dit brugernavn, så kontakt administratoren. <br><br><strong>Brugernavne uden tilhørende emailadresse vil ikke få tilsendt mail med link til reset af kodeord.</strong> ',
|
||||
'google_login' => 'Log ind med Google Workspace',
|
||||
'google_login_failed' => 'Google Log ind mislykkedes, prøv igen.',
|
||||
'invite_password_expires' => 'This password reset link will expire on :expire_date. You can use the manual password reset link to receive a new reset token by clicking here',
|
||||
|
||||
];
|
||||
|
||||
|
||||
@@ -346,6 +346,8 @@ return [
|
||||
'audit_overdue' => 'Forfalden til tilsyn',
|
||||
'accept' => 'Accepter :asset',
|
||||
'i_accept' => 'Jeg accepterer',
|
||||
'i_decline_item' => 'Decline this item',
|
||||
'i_accept_item' => 'Accept this item',
|
||||
'i_decline' => 'Jeg afviser',
|
||||
'accept_decline' => 'Accepter/afvis',
|
||||
'sign_tos' => 'Bekræft nedenfor for at angive, at du accepterer vilkårene for tjenesten:',
|
||||
@@ -594,6 +596,7 @@ return [
|
||||
'version' => 'Version',
|
||||
'build' => 'build',
|
||||
'footer_credit' => '<a target="_blank" href="https://snipeitapp.com" rel="noopener">Snipe-IT</a> is open source software, made with <i class="fa fa-heart" aria-hidden="true" style="color: #a94442; font-size: 10px" /></i><span class="sr-only">love</span> by <a href="https://bsky.app/profile/snipeitapp.com" rel="noopener">@snipeitapp.com</a>.',
|
||||
'set_password' => 'Set a Password',
|
||||
|
||||
// Add form placeholders here
|
||||
'placeholders' => [
|
||||
|
||||
@@ -8,11 +8,15 @@ return [
|
||||
'Asset_Checkout_Notification' => 'Aktiv tjekket ud',
|
||||
'Confirm_Accessory_Checkin' => 'Tilbehør checkin bekræftelse',
|
||||
'Confirm_Asset_Checkin' => 'Asset checkin bekræftelse',
|
||||
'Confirm_component_checkin' => 'Component checkin confirmation',
|
||||
'Confirm_accessory_delivery' => 'Tilbehør leveringsbekræftelse',
|
||||
'Confirm_asset_delivery' => 'Asset leveringsbekræftelse',
|
||||
'Confirm_consumable_delivery' => 'Forbrugsvare leveringsbekræftelse',
|
||||
'Confirm_component_delivery' => 'Component delivery confirmation',
|
||||
'Confirm_license_delivery' => 'Licens leveringsbekræftelse',
|
||||
'Consumable_checkout_notification' => 'Forbrugsstoffer tjekket ud',
|
||||
'Component_checkout_notification' => 'Component checked out',
|
||||
'Component_checkin_notification' => 'Component checked in',
|
||||
'Days' => 'Dage',
|
||||
'Expected_Checkin_Date' => 'Et asset tjekket ud til dig skal tjekkes tilbage den :date',
|
||||
'Expected_Checkin_Notification' => 'Påmindelse: :name checkin deadline nærmer sig',
|
||||
@@ -33,7 +37,7 @@ return [
|
||||
'send_pdf_copy' => 'Send a copy of this acceptance to my email address',
|
||||
'accessory_name' => 'Tilbehør Navn',
|
||||
'additional_notes' => 'Yderligere bemærkninger',
|
||||
'admin_has_created' => 'En administrator har oprettet en konto til dig på webstedet:.',
|
||||
'admin_has_created' => 'An administrator has created an account for you on the :web website. Please find your username below, and click on the link to set a password.',
|
||||
'asset' => 'Asset',
|
||||
'asset_name' => 'Aktivnavn',
|
||||
'asset_requested' => 'Aktiver bedt om',
|
||||
|
||||
@@ -4,7 +4,7 @@ return array(
|
||||
'asset_categories' => 'Asset-Kategorien',
|
||||
'category_name' => 'Kategorie Name',
|
||||
'checkin_email' => 'Beim Checkin/Checkout eine E-Mail an den Benutzer senden.',
|
||||
'email_to_initiator' => 'Send email to you when user accepts or declines checkout.',
|
||||
'email_to_initiator' => 'Sende eine E-Mail an Sie, wenn der Benutzer die Herausgabe akzeptiert oder ablehnt.',
|
||||
'checkin_email_notification' => 'Dieser Benutzer erhält beim Checkin / Checkout eine E-Mail.',
|
||||
'clone' => 'Kategorie duplizieren',
|
||||
'create' => 'Kategorie erstellen',
|
||||
|
||||
@@ -5,7 +5,7 @@ return [
|
||||
'manage' => 'Verwalten',
|
||||
'field' => 'Feld',
|
||||
'about_fieldsets_title' => 'Über Feldsätze',
|
||||
'about_fieldsets_text' => 'Feldsätze erlauben es, Gruppen aus benutzerdefinierten Feldern zu erstellen, die regelmäßig für spezifische Modelltypen benutzt werden.',
|
||||
'about_fieldsets_text' => 'Feldsätze sind Gruppen von benutzerdefinierten Feldern, die häufig für bestimmte Asset-Modelltypen wiederverwendet werden.',
|
||||
'custom_format' => 'Benutzerdefiniertes Regex-Format...',
|
||||
'encrypt_field' => 'Den Wert dieses Feldes in der Datenbank verschlüsseln',
|
||||
'encrypt_field_help' => 'WARNUNG: Ein verschlüsseltes Feld kann nicht durchsucht werden.',
|
||||
|
||||
@@ -55,7 +55,7 @@ return [
|
||||
'default_eula_text_placeholder' => 'Fügen Sie Ihren Standard-EULA Text hinzu',
|
||||
'default_language' => 'Standardsprache',
|
||||
'default_eula_help_text' => 'Sie können ebenfalls eigene EULA\'s mit spezifischen Asset Kategorien verknüpfen.',
|
||||
'acceptance_note' => 'Notiz für Ihre Entscheidung hinzufügen (Optional)',
|
||||
'acceptance_note' => 'Add a note for your decision (required if declining)',
|
||||
'display_asset_name' => 'Zeige Assetname an',
|
||||
'display_checkout_date' => 'Zeige Herausgabedatum',
|
||||
'display_eol' => 'Zeige EOL in der Tabellenansicht',
|
||||
@@ -157,7 +157,7 @@ return [
|
||||
'scope_locations_fmcs_support_text' => 'Bereicherte Standorte mit vollständiger Unterstützung für mehrere Unternehmen',
|
||||
'scope_locations_fmcs_support_help_text' => 'Standorte auf das ausgewählte Unternehmen beschränken.',
|
||||
'scope_locations_fmcs_check_button' => 'Kompatibilität prüfen',
|
||||
'scope_locations_fmcs_test_needed' => 'Please Check Compatibility to enable this',
|
||||
'scope_locations_fmcs_test_needed' => 'Bitte überprüfen Sie die Kompatibilität, um dies zu aktivieren',
|
||||
'scope_locations_fmcs_support_disabled_text' => 'Diese Option ist deaktiviert, da für :count oder mehr Elemente widersprüchliche Standorte gesetzt sind.',
|
||||
'show_in_model_list' => 'In Modell-Dropdown-Liste anzeigen',
|
||||
'optional' => 'optional',
|
||||
@@ -404,9 +404,9 @@ return [
|
||||
'due_checkin_days_help' => 'Wie viele Tage vor dem voraussichtlichen Check-in eines Vermögenswerts soll dieser auf der Seite „Zur Eincheckzeit fällig“ aufgeführt werden?',
|
||||
'no_groups' => 'Es wurden noch keine Gruppen erstellt. Navigieren Sie zu <code>Admin-Einstellungen > Berechtigungsgruppen</code>, um eine hinzuzufügen.',
|
||||
'text' => 'Text',
|
||||
'manager_view' => 'Manager View',
|
||||
'manager_view_enabled_text' => 'Enable Manager View',
|
||||
'manager_view_enabled_help' => 'Allow managers to view assigned items to their direct and indirect reports in their account view.',
|
||||
'manager_view' => 'Leitungsansicht',
|
||||
'manager_view_enabled_text' => 'Leitungsansicht aktivieren',
|
||||
'manager_view_enabled_help' => 'Erlaube Leitungen die ihren Mitarbeitern zugewiesenen Gegenstände in direkten und indirekten Berichten in der Account-Ansicht anzuzeigen.',
|
||||
|
||||
'username_formats' => [
|
||||
'username_format' => 'Format der Benutzernamen',
|
||||
|
||||
@@ -53,5 +53,5 @@ return [
|
||||
'next_save_user' => 'Weiter: Benutzer speichern',
|
||||
'all_assigned_list_generation' => 'Generiert am:',
|
||||
'email_user_creds_on_create' => 'Diesem Benutzer seine Zugangsdaten per E-Mail senden?',
|
||||
'department_manager' => 'Department Manager',
|
||||
'department_manager' => 'Abteilungsleiter',
|
||||
];
|
||||
|
||||
@@ -14,5 +14,7 @@ return [
|
||||
'username_help_bottom' => 'Abhängig von der Konfiguration, <em>kann</em> der Benutzername identisch mit ihrer E-Mailadresse sein. Falls Sie ihren Benutzernamen vergessen haben, kontaktieren Sie ihren Administrator.<br><br><strong>Benutzernamen ohne zugeordnete E-Mailadresse erhalten keine E-Mail zum Zurücksetzen des Passwortes.</strong> ',
|
||||
'google_login' => 'Mit Google Workspace anmelden',
|
||||
'google_login_failed' => 'Google-Anmeldung fehlgeschlagen, bitte versuchen Sie es erneut.',
|
||||
'invite_password_expires' => 'This password reset link will expire on :expire_date. You can use the manual password reset link to receive a new reset token by clicking here',
|
||||
|
||||
];
|
||||
|
||||
|
||||
@@ -225,13 +225,13 @@ return [
|
||||
'order_number' => 'Bestellnummer',
|
||||
'only_deleted' => 'Nur gelöschte Gegenstände',
|
||||
'page_menu' => 'Zeige _MENU_ Einträge',
|
||||
'page_error' => 'Could not determine previous page. Redirected to homepage.',
|
||||
'page_error' => 'Vorherige Seite konnte nicht ermittelt werden. Sie wurden auf die Startseite weitergeleitet.',
|
||||
'pagination_info' => 'Zeige _START_ bis _END_ von _TOTAL_ Einträgen',
|
||||
'pending' => 'Ausstehende',
|
||||
'people' => 'Benutzer',
|
||||
'per_page' => 'Ergebnisse pro Seite',
|
||||
'previous' => 'Vorherige',
|
||||
'previous_page' => 'Previous Page',
|
||||
'previous_page' => 'Vorherige Seite',
|
||||
'processing' => 'Wird verarbeitet',
|
||||
'profile' => 'Ihr Profil',
|
||||
'purchase_cost' => 'Einkaufspreis',
|
||||
@@ -253,7 +253,7 @@ return [
|
||||
'requested' => 'Angefordert',
|
||||
'requested_date' => 'Angefordertes Datum',
|
||||
'requested_assets' => 'Angeforderte Assets',
|
||||
'requested_assets_menu' => 'Requested Items',
|
||||
'requested_assets_menu' => 'Angeforderte Gegenstände',
|
||||
'request_canceled' => 'Anfrage abgebrochen',
|
||||
'request_item' => 'Diesen Artikel anfordern',
|
||||
'external_link_tooltip' => 'Externer Link zu',
|
||||
@@ -309,11 +309,11 @@ return [
|
||||
'type' => 'Typ',
|
||||
'undeployable' => 'Nicht herausgebbar',
|
||||
'unknown_admin' => 'Unbekannter Administrator',
|
||||
'unknown_user' => 'Unknown User',
|
||||
'unknown_user' => 'Unbekannter Benutzer',
|
||||
'username' => 'Benutzername',
|
||||
'update' => 'Aktualisieren',
|
||||
'updating_item' => ':item wird aktualisiert',
|
||||
'upload_filetypes_help' => 'Allowed filetypes are: :allowed_filetypes. Max upload size allowed is :size.',
|
||||
'upload_filetypes_help' => 'Erlaubte Dateitypen sind: :allowed_filetypes. Maximale Upload-Größe ist :size.',
|
||||
'uploaded' => 'Hochgeladen',
|
||||
'user' => 'Benutzer',
|
||||
'accepted' => 'angenommen',
|
||||
@@ -323,9 +323,9 @@ return [
|
||||
'unaccepted_asset_report' => 'Nicht akzeptierte Assets',
|
||||
'users' => 'Benutzer',
|
||||
'viewall' => 'Alle anzeigen',
|
||||
'viewassets' => 'View Assigned Items',
|
||||
'viewassetsfor' => 'View Items for :name',
|
||||
'view_user_assets' => 'View Items Assigned to User',
|
||||
'viewassets' => 'Zugewiesene Gegenstände anzeigen',
|
||||
'viewassetsfor' => 'Gegenstände von :name anzeigen',
|
||||
'view_user_assets' => 'Dem Benutzer zugewiesene Gegenstände anzeigen',
|
||||
'me' => 'Ich',
|
||||
'website' => 'Webseite',
|
||||
'welcome' => 'Willkommen, :name',
|
||||
@@ -346,6 +346,8 @@ return [
|
||||
'audit_overdue' => 'Prüfung überfällig',
|
||||
'accept' => ':asset akzeptieren',
|
||||
'i_accept' => 'Ich akzeptiere',
|
||||
'i_decline_item' => 'Decline this item',
|
||||
'i_accept_item' => 'Accept this item',
|
||||
'i_decline' => 'Ich lehne ab',
|
||||
'accept_decline' => 'Akzeptieren/Ablehnen',
|
||||
'sign_tos' => 'Unterschreiben Sie unten, um den Nutzungsbedingungen zuzustimmen:',
|
||||
@@ -516,7 +518,7 @@ return [
|
||||
'manager_last_name' => 'Vorgesetzter Nachname',
|
||||
'manager_full_name' => 'Vorgesetzter Voller Name',
|
||||
'manager_username' => 'Vorgesetzter Benutzername',
|
||||
'manager_employee_num' => 'Manager Employee Number',
|
||||
'manager_employee_num' => 'Leitungsmitarbeiternummer',
|
||||
'checkout_type' => 'Herausgabetyp',
|
||||
'checkout_location' => 'Herausgeben an Ort',
|
||||
'image_filename' => 'Bild Dateiname',
|
||||
@@ -594,6 +596,7 @@ return [
|
||||
'version' => 'Version',
|
||||
'build' => 'Build',
|
||||
'footer_credit' => '<a target="_blank" href="https://snipeitapp.com" rel="noopener">Snipe-IT</a> ist Open-Source-Software, entwickelt mit <i class="fa fa-heart" aria-hidden="true" style="color: #a94442; font-size: 10px" /></i><span class="sr-only">Liebe</span> von <a href="https://bsky.app/profile/snipeitapp.com" rel="noopener">@snipeitapp.com</a>.',
|
||||
'set_password' => 'Set a Password',
|
||||
|
||||
// Add form placeholders here
|
||||
'placeholders' => [
|
||||
@@ -645,28 +648,28 @@ return [
|
||||
'file_upload_status' => [
|
||||
|
||||
'upload' => [
|
||||
'success' => 'File successfully uploaded |:count files successfully uploaded',
|
||||
'error' => 'File upload failed |:count file uploads failed',
|
||||
'success' => 'Datei wurde erfolgreich hochgeladen|:count Dateien wurden erfolgreich hochgeladen',
|
||||
'error' => 'Datei-Upload fehlgeschlagen |:count Datei-Uploads fehlgeschlagen',
|
||||
],
|
||||
|
||||
'delete' => [
|
||||
'success' => 'File successfully deleted |:count files successfully deleted',
|
||||
'error' => 'File deletion failed |:count file deletions failed',
|
||||
'success' => 'Datei wurde erfolgreich gelöscht|:count Dateien wurden erfolgreich gelöscht',
|
||||
'error' => 'Datei-Löschung fehlgeschlagen|:count Datei-Löschungen fehlgeschlagen',
|
||||
],
|
||||
|
||||
'file_not_found' => 'The selected file was not found on server',
|
||||
'invalid_id' => 'That file ID is invalid',
|
||||
'invalid_object' => 'That object ID is invalid',
|
||||
'nofiles' => 'No files were included for upload',
|
||||
'confirm_delete' => 'Are you sure you want to delete this file?',
|
||||
'file_not_found' => 'Die ausgewählte Datei wurde nicht auf dem Server gefunden',
|
||||
'invalid_id' => 'Diese Datei-ID ist ungültig',
|
||||
'invalid_object' => 'Diese Objekt-ID ist ungültig',
|
||||
'nofiles' => 'Keine Dateien zum Hochladen vorhanden',
|
||||
'confirm_delete' => 'Sind sie sicher das diese Datei gelöscht werden soll?',
|
||||
],
|
||||
|
||||
'depreciation_options' => [
|
||||
'amount' => 'Amount',
|
||||
'percent' => 'Percentage',
|
||||
'amount' => 'Anzahl',
|
||||
'percent' => 'Prozentsatz',
|
||||
],
|
||||
|
||||
'months_plural' => '1 month|:count months',
|
||||
'months_plural' => '1 Monat|:count Monate',
|
||||
|
||||
|
||||
];
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user