Compare commits
84 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 240196c3a1 | |||
| 409ce69e32 | |||
| 0bdd3034d1 | |||
| f04a41408d | |||
| 15effb1974 | |||
| ccd60eb6d0 | |||
| 2f54f5b051 | |||
| 509584d1ff | |||
| 95ac268046 | |||
| f4b9736862 | |||
| a0bf7a018c | |||
| ac4975e1d1 | |||
| c7c3b04c5f | |||
| 88f87db4fd | |||
| ad0199f662 | |||
| 75a276d9fa | |||
| ead0047629 | |||
| 46f6766bb4 | |||
| 8a470d3ef9 | |||
| 5506245959 | |||
| 0fc175581a | |||
| cd9005f82b | |||
| 24237d4259 | |||
| b2d707aaab | |||
| a432f23692 | |||
| a63b9ec627 | |||
| a35820d612 | |||
| ecf8ce3ec1 | |||
| 1908beb671 | |||
| 1872c6eed9 | |||
| 53199b9737 | |||
| 73861c6a04 | |||
| e2969dd3e2 | |||
| c5296fd76d | |||
| 3cb3284b26 | |||
| d5d0d00ecc | |||
| 5db9d67e65 | |||
| f64dfa7f92 | |||
| 06584d17a6 | |||
| 75cb1041ec | |||
| b61ed66d9d | |||
| 48ebd7faf5 | |||
| d6de3baa6e | |||
| 1be44a4c05 | |||
| f17f34f730 | |||
| da5bb6126a | |||
| a5d04d2e65 | |||
| 22d07214fe | |||
| 8d4523d250 | |||
| 37a3d694d4 | |||
| d21ccdfcbf | |||
| 4eba97d388 | |||
| 613137551a | |||
| 23f941c810 | |||
| e7312801ac | |||
| cd69a7ea53 | |||
| 13ffdda12e | |||
| 372e74aad3 | |||
| 2a32f7d372 | |||
| a2d34cca76 | |||
| c513ed5fc3 | |||
| 34cd5dcf7c | |||
| 16e981d99d | |||
| 16eb899ba7 | |||
| 3367f8e5c7 | |||
| ad635ab95c | |||
| b94e7fd8a0 | |||
| 683fbd7953 | |||
| 246ec9e20b | |||
| 81d669d62a | |||
| 9ff951d379 | |||
| e327303b3c | |||
| 1c5d81cb04 | |||
| d37f43daba | |||
| dbabd1bab3 | |||
| 6b5398139a | |||
| 0ec45a4fd0 | |||
| b99fd237f3 | |||
| 5d7123eb05 | |||
| 7eb6ebb60d | |||
| 5bc273686e | |||
| 37a37318aa | |||
| c6619a621c | |||
| 565e3de183 |
@@ -4262,6 +4262,15 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Husky-Devel",
|
||||
"name": "Peter Gallwas",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/75509373?v=4",
|
||||
"profile": "https://www.husky.nz",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+1
-1
@@ -69,7 +69,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
|
||||
| [<img src="https://avatars.githubusercontent.com/u/10965027?v=4" width="110px;"/><br /><sub>Ellie</sub>](https://leafedfox.xyz/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=LeafedFox "Code") | [<img src="https://avatars.githubusercontent.com/u/20960555?v=4" width="110px;"/><br /><sub>GA Stamper</sub>](https://github.com/gastamper)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gastamper "Code") | [<img src="https://avatars.githubusercontent.com/u/206553556?v=4" width="110px;"/><br /><sub>Guillaume Lefranc</sub>](https://github.com/gl-pup)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gl-pup "Code") | [<img src="https://avatars.githubusercontent.com/u/733892?v=4" width="110px;"/><br /><sub>Hajo Möller</sub>](https://github.com/dasjoe)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dasjoe "Code") | [<img src="https://avatars.githubusercontent.com/u/3420063?v=4" width="110px;"/><br /><sub>Istvan Basa</sub>](https://github.com/pottom)<br />[💻](https://github.com/snipe/snipe-it/commits?author=pottom "Code") | [<img src="https://avatars.githubusercontent.com/u/810824?v=4" width="110px;"/><br /><sub>JJ Asghar</sub>](https://jjasghar.github.io/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jjasghar "Code") | [<img src="https://avatars.githubusercontent.com/u/40404495?v=4" width="110px;"/><br /><sub>James E. Msenga</sub>](https://github.com/JemCdo)<br />[💻](https://github.com/snipe/snipe-it/commits?author=JemCdo "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/6865786?v=4" width="110px;"/><br /><sub>Jan Felix Wiebe</sub>](https://github.com/jfwiebe)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jfwiebe "Code") | [<img src="https://avatars.githubusercontent.com/u/43412008?v=4" width="110px;"/><br /><sub>Jo Drexl</sub>](https://www.nfon.com/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=drexljo "Code") | [<img src="https://avatars.githubusercontent.com/u/4807843?v=4" width="110px;"/><br /><sub>Austin Sasko</sub>](https://github.com/austinsasko)<br />[💻](https://github.com/snipe/snipe-it/commits?author=austinsasko "Code") | [<img src="https://avatars.githubusercontent.com/u/4875039?v=4" width="110px;"/><br /><sub>Jasson</sub>](http://jassoncordones.github.io)<br />[💻](https://github.com/snipe/snipe-it/commits?author=JassonCordones "Code") | [<img src="https://avatars.githubusercontent.com/u/76069640?v=4" width="110px;"/><br /><sub>Okean</sub>](https://github.com/Tinyblargon)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Tinyblargon "Code") | [<img src="https://avatars.githubusercontent.com/u/6515064?v=4" width="110px;"/><br /><sub>Alejandro Medrano</sub>](https://www.lst.tfo.upm.es/alejandro-medrano/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=amedranogil "Code") | [<img src="https://avatars.githubusercontent.com/u/58696401?v=4" width="110px;"/><br /><sub>Lukas Kraic</sub>](https://github.com/lukaskraic)<br />[💻](https://github.com/snipe/snipe-it/commits?author=lukaskraic "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/1571724?v=4" width="110px;"/><br /><sub>Герхард PICCORO Lenz McKAY </sub>](https://github-readme-stats.vercel.app/api?username=mckaygerhard)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mckaygerhard "Code") | [<img src="https://avatars.githubusercontent.com/u/15015119?v=4" width="110px;"/><br /><sub>Johannes Pollitt</sub>](https://github.com/FlorestanII)<br />[💻](https://github.com/snipe/snipe-it/commits?author=FlorestanII "Code") | [<img src="https://avatars.githubusercontent.com/u/14185442?v=4" width="110px;"/><br /><sub>Michael Strobel</sub>](https://strobelm.de)<br />[💻](https://github.com/snipe/snipe-it/commits?author=strobelm "Code") | [<img src="https://avatars.githubusercontent.com/u/634790?v=4" width="110px;"/><br /><sub>Nicky West</sub>](http://nickwest.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=nickwest "Code") | [<img src="https://avatars.githubusercontent.com/u/1347327?v=4" width="110px;"/><br /><sub>akaspeh1</sub>](https://github.com/akaspeh1)<br />[💻](https://github.com/snipe/snipe-it/commits?author=akaspeh1 "Code") | [<img src="https://avatars.githubusercontent.com/u/2880129?v=4" width="110px;"/><br /><sub>Sebastian Marsching</sub>](http://sebastian.marsching.com/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=smarsching "Code") | [<img src="https://avatars.githubusercontent.com/u/40658372?v=4" width="110px;"/><br /><sub>Mo</sub>](https://github.com/mohammad-ahmadi1)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mohammad-ahmadi1 "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/20994684?v=4" width="110px;"/><br /><sub>Owen V. Hayes</sub>](https://github.com/MarvelousAnything)<br />[💻](https://github.com/snipe/snipe-it/commits?author=MarvelousAnything "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/20994684?v=4" width="110px;"/><br /><sub>Owen V. Hayes</sub>](https://github.com/MarvelousAnything)<br />[💻](https://github.com/snipe/snipe-it/commits?author=MarvelousAnything "Code") | [<img src="https://avatars.githubusercontent.com/u/75509373?v=4" width="110px;"/><br /><sub>Peter Gallwas</sub>](https://www.husky.nz)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Husky-Devel "Code") |
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
||||
@@ -13,6 +13,7 @@ enum ActionType: string
|
||||
// Assets/Accessories/Components/Licenses/Consumables
|
||||
case Checkout = 'checkout';
|
||||
case CheckinFrom = 'checkin from';
|
||||
case ForceCheckin = 'force checkin';
|
||||
case Requested = 'requested';
|
||||
case RequestCanceled = 'request canceled';
|
||||
case Accepted = 'accepted';
|
||||
|
||||
@@ -6,6 +6,7 @@ use App\Events\CheckoutAccepted;
|
||||
use App\Events\CheckoutDeclined;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\AcceptSignatureRequest;
|
||||
use App\Mail\CheckoutAcceptanceResponseMail;
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Actionlog;
|
||||
@@ -36,7 +37,8 @@ class AcceptanceController extends Controller
|
||||
*/
|
||||
public function index(): View
|
||||
{
|
||||
$acceptances = CheckoutAcceptance::forUser(auth()->user())->pending()->get();
|
||||
$user = auth()->user();
|
||||
$acceptances = CheckoutAcceptance::forUser($user)->pending()->get();
|
||||
|
||||
return view('account/accept.index', compact('acceptances'));
|
||||
}
|
||||
@@ -51,13 +53,13 @@ class AcceptanceController extends Controller
|
||||
$currentUser = auth()->user();
|
||||
|
||||
if (! $currentUser instanceof User) {
|
||||
abort(403, trans('general.insufficient_permissions'));
|
||||
return redirect()->route('account.accept')->with('error', trans('general.insufficient_permissions'));
|
||||
}
|
||||
|
||||
$acceptance = CheckoutAcceptance::find($id);
|
||||
|
||||
if (! $acceptance) {
|
||||
return redirect()->route('account.accept')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
return redirect()->route('account.accept')->with('error', trans('general.generic_model_not_found', ['model' => trans('general.accept_eula')]));
|
||||
}
|
||||
|
||||
if (! $acceptance->isPending()) {
|
||||
@@ -76,7 +78,7 @@ class AcceptanceController extends Controller
|
||||
}
|
||||
|
||||
if (! Company::isCurrentUserHasAccess($acceptance->checkoutable)) {
|
||||
return redirect()->route('account.accept')->with('error', trans('general.error_user_company'));
|
||||
return redirect()->route('account.accept')->with('error', trans('general.insufficient_permissions'));
|
||||
}
|
||||
|
||||
$checkedOutAt = Helper::getFormattedDateObject($acceptance->created_at, 'datetime', false);
|
||||
@@ -90,18 +92,12 @@ class AcceptanceController extends Controller
|
||||
*
|
||||
* @param int $id
|
||||
*/
|
||||
public function store(Request $request, $id): RedirectResponse
|
||||
public function store(AcceptSignatureRequest $request, CheckoutAcceptance $acceptance): RedirectResponse
|
||||
{
|
||||
$currentUser = auth()->user();
|
||||
|
||||
if (! $currentUser instanceof User) {
|
||||
abort(403, trans('general.insufficient_permissions'));
|
||||
}
|
||||
|
||||
$acceptance = CheckoutAcceptance::find($id);
|
||||
|
||||
if (! $acceptance) {
|
||||
return redirect()->route('account.accept')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
return redirect()->route('account.accept')->with('error', trans('general.insufficient_permissions'));
|
||||
}
|
||||
|
||||
$assignedUser = User::find($acceptance->assigned_to_id);
|
||||
@@ -182,7 +178,34 @@ class AcceptanceController extends Controller
|
||||
// This is needed for TCPDF to properly embed the image if it's a png and the cache isn't writable
|
||||
$encoded_logo = null;
|
||||
if (($settings->acceptance_pdf_logo) && (Storage::disk('public')->exists($settings->acceptance_pdf_logo))) {
|
||||
$encoded_logo = base64_encode(file_get_contents(public_path().'/uploads/'.$settings->acceptance_pdf_logo));
|
||||
$encoded_logo = base64_encode(file_get_contents(public_path().'/uploads/'.basename($settings->acceptance_pdf_logo)));
|
||||
}
|
||||
|
||||
if ($isSignInPlaceAdminFlow && (! $acceptance->signed_in_place || (int) $acceptance->signed_in_place_admin !== (int) $currentUser->id)) {
|
||||
$acceptance->forceFill([
|
||||
'signed_in_place' => true,
|
||||
'signed_in_place_admin' => $currentUser->id,
|
||||
])->save();
|
||||
}
|
||||
|
||||
// Determine signed_in_place and admin for PDF/email output
|
||||
$signedInPlace = $isSignInPlaceAdminFlow ? true : (bool) $acceptance->signed_in_place;
|
||||
$signedInPlaceAdmin = null;
|
||||
if ($isSignInPlaceAdminFlow) {
|
||||
$signedInPlaceAdmin = [
|
||||
'name' => $currentUser->display_name,
|
||||
'username' => $currentUser->username,
|
||||
'email' => $currentUser->email,
|
||||
];
|
||||
} elseif ($acceptance->signed_in_place && $acceptance->signed_in_place_admin) {
|
||||
$admin = User::find($acceptance->signed_in_place_admin);
|
||||
if ($admin) {
|
||||
$signedInPlaceAdmin = [
|
||||
'name' => $admin->display_name,
|
||||
'username' => $admin->username,
|
||||
'email' => $admin->email,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Get the data array ready for the notifications and PDF generation
|
||||
@@ -206,21 +229,46 @@ class AcceptanceController extends Controller
|
||||
'logo' => ($encoded_logo) ?? null,
|
||||
'date_settings' => $settings->date_display_format,
|
||||
'qty' => $acceptance->qty ?? 1,
|
||||
'signed_in_place' => $signedInPlace,
|
||||
];
|
||||
if ($signedInPlaceAdmin) {
|
||||
$data['signed_in_place_admin'] = $signedInPlaceAdmin;
|
||||
}
|
||||
|
||||
// Add custom fields for asset (show_in_email = 1, field_encrypted = 0)
|
||||
$customFields = [];
|
||||
if ($item instanceof Asset && $item->model && $item->model->fieldset) {
|
||||
$fields = $item->model->fieldset->fields->where('show_in_email', true)->where('field_encrypted', false);
|
||||
foreach ($fields as $field) {
|
||||
$label = $field->name;
|
||||
$dbColumn = $field->db_column;
|
||||
$value = $item->$dbColumn;
|
||||
if (! is_null($value) && $value !== '') {
|
||||
$customFields[] = [
|
||||
'label' => $label,
|
||||
'value' => $value,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! empty($customFields)) {
|
||||
$data['custom_fields'] = $customFields;
|
||||
}
|
||||
|
||||
if ($request->input('asset_acceptance') === 'accepted') {
|
||||
|
||||
$pdf_filename = 'accepted-'.$acceptance->checkoutable_id.'-'.$acceptance->display_checkoutable_type.'-eula-'.date('Y-m-d-h-i-s').'.pdf';
|
||||
|
||||
// Generate the PDF content
|
||||
$pdf_content = $acceptance->generateAcceptancePdf($data, $acceptance);
|
||||
Storage::put('private_uploads/eula-pdfs/'.$pdf_filename, $pdf_content);
|
||||
|
||||
// Log the acceptance
|
||||
$acceptance->accept($sig_filename, $item->getEula(), $pdf_filename, $request->input('note'));
|
||||
$accept_qty = $request->input('accept_qty', $acceptance->qty ?? 1);
|
||||
$acceptance->accept($sig_filename, $item->getEula(), $pdf_filename, $request->input('note'), $accept_qty);
|
||||
|
||||
$alwaysSendAcceptanceCopy = (bool) (config('app.always_send_email') || config('app.always_send_eula'));
|
||||
|
||||
// Send the PDF to the signing user
|
||||
if (($request->input('send_copy') === '1') && ($assignedUser->email !== '')) {
|
||||
if (($alwaysSendAcceptanceCopy || ($request->input('send_copy') === '1')) && ($assignedUser->email !== '')) {
|
||||
|
||||
// Add the attachment for the signing user into the $data array
|
||||
$data['file'] = $pdf_filename;
|
||||
|
||||
@@ -15,6 +15,8 @@ class ActionlogController extends Controller
|
||||
{
|
||||
public function displaySig($filename): RedirectResponse|Response|bool
|
||||
{
|
||||
$filename = basename((string) $filename);
|
||||
|
||||
// PHP doesn't let you handle file not found errors well with
|
||||
// file_get_contents, so we set the error reporting for just this class
|
||||
error_reporting(0);
|
||||
@@ -44,6 +46,7 @@ class ActionlogController extends Controller
|
||||
|
||||
public function getStoredEula($filename): Response|BinaryFileResponse|RedirectResponse
|
||||
{
|
||||
$filename = basename((string) $filename);
|
||||
|
||||
if ($actionlog = Actionlog::where('filename', $filename)->with('user')->with('target')->firstOrFail()) {
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* This class controls all actions related to assets for
|
||||
@@ -1122,11 +1123,23 @@ class AssetsController extends Controller
|
||||
$dt = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
|
||||
}
|
||||
|
||||
// Allow the asset tag to be passed in the payload (legacy method)
|
||||
if ($request->filled('asset_tag')) {
|
||||
$audit_by_field = $request->input('audit_by_field', 'asset_tag');
|
||||
$audit_key = $request->input('audit_key', null);
|
||||
|
||||
// If they have selected to scan by serial, use that
|
||||
if (($settings->unique_serial == '1') && ($audit_by_field == 'serial') && ($audit_key)) {
|
||||
$asset = Asset::where('serial', '=', trim($audit_key))->first();
|
||||
|
||||
// If they have selected by asset tag, use that
|
||||
} elseif (($audit_by_field == 'asset_tag') && ($audit_key)) {
|
||||
$asset = Asset::where('asset_tag', '=', trim($audit_key))->first();
|
||||
|
||||
// Allow the asset tag to be passed in the payload (legacy method)
|
||||
} elseif ($request->filled('asset_tag')) {
|
||||
$asset = Asset::where('asset_tag', '=', $request->input('asset_tag'))->first();
|
||||
}
|
||||
|
||||
// If none of the above were selected, fall back to the route-model-binding
|
||||
if ($asset) {
|
||||
|
||||
$originalValues = $asset->getRawOriginal();
|
||||
@@ -1148,8 +1161,10 @@ class AssetsController extends Controller
|
||||
// Set up the payload for re-display in the API response
|
||||
$payload = [
|
||||
'id' => $asset->id,
|
||||
'asset_tag' => $asset->asset_tag,
|
||||
'note' => e($request->input('note')),
|
||||
'asset_tag' => e($asset->asset_tag),
|
||||
'audit_by_field' => e(Str::headline($audit_by_field)),
|
||||
'audit_key' => e($audit_key),
|
||||
'note' => $request->filled('note') ? e($request->input('note')) : null,
|
||||
'status_label' => e($asset->status?->display_name),
|
||||
'status_type' => $asset->status?->getStatuslabelType(),
|
||||
'next_audit_date' => Helper::getFormattedDateObject($asset->next_audit_date),
|
||||
@@ -1190,7 +1205,7 @@ class AssetsController extends Controller
|
||||
|
||||
// Validate the rest of the data before we turn off the event dispatcher
|
||||
if ($asset->isInvalid()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', ['asset_tag' => $asset->asset_tag], $asset->getErrors()));
|
||||
return response()->json(Helper::formatStandardApiResponse('error', $payload, $asset->getErrors()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1223,8 +1238,13 @@ class AssetsController extends Controller
|
||||
|
||||
}
|
||||
|
||||
$fail_payload = [
|
||||
'audit_by_field' => e(Str::headline($audit_by_field)),
|
||||
'audit_key' => e($audit_key),
|
||||
];
|
||||
|
||||
// No matching asset for the asset tag that was passed.
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
|
||||
return response()->json(Helper::formatStandardApiResponse('error', $fail_payload, trans('admin/hardware/message.does_not_exist')), 200);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -129,6 +129,11 @@ class CategoriesController extends Controller
|
||||
case 'created_by':
|
||||
$categories = $categories->OrderByCreatedBy($order);
|
||||
break;
|
||||
// This is annoying, since it's not a real relationship, which is what we usually use these switches for, but
|
||||
// we call the field has_eula, not eula_text, so there won't be a matching field
|
||||
case 'has_eula':
|
||||
$categories = $categories->orderBy('eula_text', $order);
|
||||
break;
|
||||
default:
|
||||
$categories = $categories->orderBy($column_sort, $order);
|
||||
break;
|
||||
|
||||
@@ -165,6 +165,7 @@ class SettingsController extends Controller
|
||||
|
||||
if (config('mail.reply_to.address') == '') {
|
||||
Log::debug('MAIL_REPLYTO_ADDR not set in env. Skipping mail test.');
|
||||
|
||||
return response()->json(['message' => trans('admin/settings/general.mail_test_no_email')], 403);
|
||||
}
|
||||
|
||||
@@ -292,6 +293,11 @@ class SettingsController extends Controller
|
||||
*/
|
||||
public function downloadBackup($file): JsonResponse|BinaryFileResponse
|
||||
{
|
||||
$file = $this->sanitizeBackupFilename($file);
|
||||
|
||||
if ($file === null) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.file_not_found')), 404);
|
||||
}
|
||||
|
||||
$path = storage_path('app/backups');
|
||||
|
||||
@@ -335,4 +341,21 @@ class SettingsController extends Controller
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function sanitizeBackupFilename(mixed $filename): ?string
|
||||
{
|
||||
$filename = trim((string) $filename);
|
||||
|
||||
if ($filename === '' || str_contains($filename, "\0")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$sanitized = basename($filename);
|
||||
|
||||
if (($sanitized === '') || ($sanitized === '.') || ($sanitized === '..')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ($sanitized === $filename) ? $sanitized : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,4 +185,34 @@ class AssetCheckinController extends Controller
|
||||
// Redirect to the asset management page with error
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.error').$asset->getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
* This would only be used if the target is actually hard-deleted
|
||||
* and literally does not exist in the database anymore. This will null out the assigned_to
|
||||
* and assigned_type fields, but will not trigger any events or do any of the other things that a
|
||||
* normal checkin would do, since the target itself is now invalid.
|
||||
*/
|
||||
public function forceCheckin(Asset $asset)
|
||||
{
|
||||
|
||||
$this->authorize('checkin', $asset);
|
||||
|
||||
if (! $asset->hasOrphanedAssignment()) {
|
||||
return redirect()->route('hardware.show', $asset->id)
|
||||
->with('error', trans('admin/hardware/message.checkin.force_checkin_not_orphaned'));
|
||||
}
|
||||
|
||||
$asset->assigned_to = null;
|
||||
$asset->assigned_type = null;
|
||||
|
||||
if ($asset->save()) {
|
||||
$asset->logForceCheckin();
|
||||
|
||||
return redirect()->route('hardware.show', $asset->id)
|
||||
->with('success', trans('admin/hardware/message.checkin.force_checkin_orphaned_success'));
|
||||
}
|
||||
|
||||
return redirect()->route('hardware.show', $asset->id)
|
||||
->with('error', trans('admin/hardware/message.checkin.force_checkin_error'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,33 +25,27 @@ class ConsumableCheckoutController extends Controller
|
||||
*
|
||||
* @param int $id
|
||||
*/
|
||||
public function create($id): View|RedirectResponse
|
||||
public function create(Consumable $consumable): View|RedirectResponse
|
||||
{
|
||||
|
||||
if ($consumable = Consumable::find($id)) {
|
||||
$this->authorize('checkout', $consumable);
|
||||
|
||||
$this->authorize('checkout', $consumable);
|
||||
// Make sure the category is valid
|
||||
if ($consumable->category) {
|
||||
|
||||
// Make sure the category is valid
|
||||
if ($consumable->category) {
|
||||
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($consumable->numRemaining() <= 0) {
|
||||
return redirect()->route('consumables.index')
|
||||
->with('error', trans('admin/consumables/message.checkout.unavailable', ['requested' => 1, 'remaining' => $consumable->numRemaining()]));
|
||||
}
|
||||
|
||||
// Return the checkout view
|
||||
return view('consumables/checkout', compact('consumable'));
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($consumable->numRemaining() <= 0) {
|
||||
return redirect()->route('consumables.index')
|
||||
->with('error', trans('admin/consumables/message.checkout.unavailable', ['requested' => 1, 'remaining' => $consumable->numRemaining()]));
|
||||
}
|
||||
|
||||
// Invalid category
|
||||
return redirect()->route('consumables.edit', ['consumable' => $consumable->id])
|
||||
->with('error', trans('general.invalid_item_category_single', ['type' => trans('general.consumable')]));
|
||||
// Return the checkout view
|
||||
return view('consumables/checkout', compact('consumable'));
|
||||
}
|
||||
|
||||
// Not found
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
|
||||
// Invalid category
|
||||
return redirect()->route('consumables.edit', ['consumable' => $consumable->id])
|
||||
->with('error', trans('general.invalid_item_category_single', ['type' => trans('general.consumable')]));
|
||||
|
||||
}
|
||||
|
||||
@@ -68,12 +62,8 @@ class ConsumableCheckoutController extends Controller
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
*/
|
||||
public function store(Request $request, $consumableId)
|
||||
public function store(Request $request, Consumable $consumable)
|
||||
{
|
||||
if (is_null($consumable = Consumable::with('users')->find($consumableId))) {
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.not_found'));
|
||||
}
|
||||
|
||||
$this->authorize('checkout', $consumable);
|
||||
|
||||
// If the quantity is not present in the request or is not a positive integer, set it to 1
|
||||
@@ -99,14 +89,14 @@ class ConsumableCheckoutController extends Controller
|
||||
// Update the consumable data
|
||||
$consumable->assigned_to = e($request->input('assigned_to'));
|
||||
|
||||
for ($i = 0; $i < $quantity; $i++) {
|
||||
$consumable->users()->attach($consumable->id, [
|
||||
'consumable_id' => $consumable->id,
|
||||
'created_by' => $admin_user->id,
|
||||
'assigned_to' => e($request->input('assigned_to')),
|
||||
'note' => $request->input('note'),
|
||||
]);
|
||||
}
|
||||
// Attach the consumable to the user ONCE with the correct qty and note
|
||||
$consumable->users()->attach($consumable->id, [
|
||||
'consumable_id' => $consumable->id,
|
||||
'created_by' => $admin_user->id,
|
||||
'assigned_to' => $assigned_to,
|
||||
'note' => $request->input('note'),
|
||||
'qty' => $quantity,
|
||||
]);
|
||||
|
||||
$consumable->checkout_qty = $quantity;
|
||||
|
||||
|
||||
@@ -251,6 +251,7 @@ class ProfileController extends Controller
|
||||
|
||||
public function getStoredEula($filename): Response|BinaryFileResponse|RedirectResponse
|
||||
{
|
||||
$filename = basename((string) $filename);
|
||||
|
||||
$logentry = Actionlog::where('filename', $filename)->first();
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use League\Csv\EscapeFormula;
|
||||
@@ -1070,7 +1071,13 @@ class ReportsController extends Controller
|
||||
foreach ($customfields as $customfield) {
|
||||
$column_name = $customfield->db_column_name();
|
||||
if ($request->filled($customfield->db_column_name())) {
|
||||
$row[] = $asset->$column_name;
|
||||
$value = $asset->$column_name;
|
||||
|
||||
if (($customfield->field_encrypted == '1') && Gate::allows('assets.view.encrypted_custom_fields')) {
|
||||
$value = Helper::gracefulDecrypt($customfield, $value);
|
||||
}
|
||||
|
||||
$row[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1211,7 +1218,7 @@ class ReportsController extends Controller
|
||||
->filter(fn ($unaccepted) => $unaccepted->checkoutable)
|
||||
->map(fn ($unaccepted) => Checkoutable::fromAcceptance($unaccepted));
|
||||
|
||||
return view('reports/unaccepted_assets', compact('itemsForReport', 'showDeleted'));
|
||||
return view('reports/unaccepted_items', compact('itemsForReport', 'showDeleted'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1223,6 +1230,10 @@ class ReportsController extends Controller
|
||||
*/
|
||||
public function sentAssetAcceptanceReminder(Request $request): RedirectResponse
|
||||
{
|
||||
$user = auth()->user();
|
||||
if (! ($user?->isAdmin() || $user?->isSuperUser())) {
|
||||
abort(403);
|
||||
}
|
||||
$this->authorize('reports.view');
|
||||
$id = $request->input('acceptance_id');
|
||||
$query = CheckoutAcceptance::query()
|
||||
@@ -1244,7 +1255,7 @@ class ReportsController extends Controller
|
||||
Log::debug('No pending acceptances');
|
||||
|
||||
// Redirect to the unaccepted items report page with error
|
||||
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.bad_data'));
|
||||
return redirect()->route('reports/unaccepted_items')->with('error', trans('general.bad_data_or_already_accepted'));
|
||||
}
|
||||
$item = $acceptance->checkoutable;
|
||||
$assignee = $acceptance->assignedTo ?? $item->assignedTo ?? null;
|
||||
@@ -1256,7 +1267,7 @@ class ReportsController extends Controller
|
||||
if (is_null($acceptance->created_at)) {
|
||||
Log::debug('No acceptance created_at');
|
||||
|
||||
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.bad_data'));
|
||||
return redirect()->route('reports/unaccepted_items')->with('error', trans('general.bad_data_or_already_accepted'));
|
||||
} else {
|
||||
if ($item instanceof LicenseSeat) {
|
||||
$logItem_res = $item->license->checkouts()->with('adminuser')->where('created_at', '=', $acceptance->created_at)->get();
|
||||
@@ -1266,18 +1277,18 @@ class ReportsController extends Controller
|
||||
if ($logItem_res->isEmpty()) {
|
||||
Log::debug('Acceptance date mismatch');
|
||||
|
||||
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.bad_data'));
|
||||
return redirect()->route('reports/unaccepted_items')->with('error', trans('general.bad_data_or_already_accepted'));
|
||||
}
|
||||
$logItem = $logItem_res[0];
|
||||
}
|
||||
|
||||
if (is_null($email) || $email === '') {
|
||||
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.no_email'));
|
||||
return redirect()->route('reports/unaccepted_items')->with('error', trans('general.no_email'));
|
||||
}
|
||||
$mailable = $this->getCheckoutMailType($acceptance, $logItem);
|
||||
Mail::to($email)->send($mailable->locale($locale));
|
||||
|
||||
return redirect()->route('reports/unaccepted_assets')->with('success', trans('admin/reports/general.reminder_sent'));
|
||||
return redirect()->route('reports/unaccepted_items')->with('success', trans('admin/reports/general.reminder_sent'));
|
||||
}
|
||||
|
||||
private function getCheckoutMailType(CheckoutAcceptance $acceptance, $logItem): Mailable
|
||||
@@ -1310,17 +1321,21 @@ class ReportsController extends Controller
|
||||
*/
|
||||
public function deleteAssetAcceptance($acceptanceId = null): RedirectResponse
|
||||
{
|
||||
$user = auth()->user();
|
||||
if (! ($user?->isAdmin() || $user?->isSuperUser())) {
|
||||
abort(403);
|
||||
}
|
||||
$this->authorize('reports.view');
|
||||
|
||||
if (! $acceptance = CheckoutAcceptance::pending()->find($acceptanceId)) {
|
||||
// Redirect to the unaccepted assets report page with error
|
||||
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.bad_data'));
|
||||
return redirect()->route('reports/unaccepted_items')->with('error', trans('general.bad_data_or_already_accepted'));
|
||||
}
|
||||
|
||||
if ($acceptance->delete()) {
|
||||
return redirect()->route('reports/unaccepted_assets')->with('success', trans('admin/reports/general.acceptance_deleted'));
|
||||
return redirect()->route('reports/unaccepted_items')->with('success', trans('admin/reports/general.acceptance_deleted'));
|
||||
} else {
|
||||
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.deletion_failed'));
|
||||
return redirect()->route('reports/unaccepted_items')->with('error', trans('general.deletion_failed'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -872,6 +872,11 @@ class SettingsController extends Controller
|
||||
public function downloadFile($filename = null): RedirectResponse|BinaryFileResponse
|
||||
{
|
||||
$path = 'app/backups';
|
||||
$filename = basename((string) $filename);
|
||||
|
||||
if ($this->hasInvalidBackupFilename($filename)) {
|
||||
return redirect()->route('settings.backups.index')->with('error', trans('admin/settings/message.backup.file_not_found'));
|
||||
}
|
||||
|
||||
if (! config('app.lock_passwords')) {
|
||||
if (Storage::exists($path.'/'.$filename)) {
|
||||
@@ -897,6 +902,12 @@ class SettingsController extends Controller
|
||||
*/
|
||||
public function deleteFile($filename = null): RedirectResponse
|
||||
{
|
||||
$filename = basename((string) $filename);
|
||||
|
||||
if ($this->hasInvalidBackupFilename($filename)) {
|
||||
return redirect()->route('settings.backups.index')->with('error', trans('admin/settings/message.backup.file_not_found'));
|
||||
}
|
||||
|
||||
if (config('app.allow_backup_delete') == 'true') {
|
||||
|
||||
if (! config('app.lock_passwords')) {
|
||||
@@ -971,6 +982,11 @@ class SettingsController extends Controller
|
||||
*/
|
||||
public function postRestore(Request $request, $filename = null): RedirectResponse
|
||||
{
|
||||
$filename = basename((string) $filename);
|
||||
|
||||
if ($this->hasInvalidBackupFilename($filename)) {
|
||||
return redirect()->route('settings.backups.index')->with('error', trans('admin/settings/message.backup.file_not_found'));
|
||||
}
|
||||
|
||||
if (! config('app.lock_passwords')) {
|
||||
$path = 'app/backups';
|
||||
@@ -1284,4 +1300,14 @@ class SettingsController extends Controller
|
||||
->to(route('settings.oauth.index').'#oauth-clients')
|
||||
->with('success', trans('admin/settings/message.oauth.client_unrevoked'));
|
||||
}
|
||||
|
||||
private function hasInvalidBackupFilename(string $filename): bool
|
||||
{
|
||||
if ($filename === '' || $filename === '.' || $filename === '..') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Reject path separators in case a crafted value survives route decoding.
|
||||
return str_contains($filename, '/') || str_contains($filename, '\\');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,13 +17,17 @@ class StorageProxyController extends Controller
|
||||
*/
|
||||
public function show(string $path): Response|StreamedResponse
|
||||
{
|
||||
if ($this->hasPathTraversalSegments($path)) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
$disk = Storage::disk('public');
|
||||
|
||||
// The S3 adapter includes the disk's root prefix in generated URLs,
|
||||
// but Flysystem also prepends it internally on every operation.
|
||||
// Strip it here to avoid double-prefixing.
|
||||
$root = trim(config('filesystems.disks.public.root', ''), '/');
|
||||
if ($root !== '' && str_starts_with($path, $root . '/')) {
|
||||
if ($root !== '' && str_starts_with($path, $root.'/')) {
|
||||
$path = substr($path, strlen($root) + 1);
|
||||
}
|
||||
|
||||
@@ -33,12 +37,12 @@ class StorageProxyController extends Controller
|
||||
|
||||
$mimeType = $disk->mimeType($path) ?: 'application/octet-stream';
|
||||
$lastModified = $disk->lastModified($path);
|
||||
$etag = md5($path . $lastModified);
|
||||
$etag = md5($path.$lastModified);
|
||||
$size = $disk->size($path);
|
||||
|
||||
if ($this->isNotModified($etag, $lastModified)) {
|
||||
return response('', 304)
|
||||
->header('ETag', '"' . $etag . '"')
|
||||
->header('ETag', '"'.$etag.'"')
|
||||
->header('Cache-Control', 'public, max-age=86400');
|
||||
}
|
||||
|
||||
@@ -51,8 +55,8 @@ class StorageProxyController extends Controller
|
||||
}, 200, [
|
||||
'Content-Type' => $mimeType,
|
||||
'Content-Length' => $size,
|
||||
'ETag' => '"' . $etag . '"',
|
||||
'Last-Modified' => gmdate('D, d M Y H:i:s', $lastModified) . ' GMT',
|
||||
'ETag' => '"'.$etag.'"',
|
||||
'Last-Modified' => gmdate('D, d M Y H:i:s', $lastModified).' GMT',
|
||||
'Cache-Control' => 'public, max-age=86400',
|
||||
]);
|
||||
}
|
||||
@@ -60,7 +64,7 @@ class StorageProxyController extends Controller
|
||||
private function isNotModified(string $etag, int $lastModified): bool
|
||||
{
|
||||
$requestEtag = request()->header('If-None-Match');
|
||||
if ($requestEtag && $requestEtag === '"' . $etag . '"') {
|
||||
if ($requestEtag && $requestEtag === '"'.$etag.'"') {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -71,4 +75,16 @@ class StorageProxyController extends Controller
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function hasPathTraversalSegments(string $path): bool
|
||||
{
|
||||
$normalizedPath = str_replace('\\', '/', $path);
|
||||
|
||||
return str_contains($normalizedPath, "\0")
|
||||
|| str_starts_with($normalizedPath, '/')
|
||||
|| str_contains($normalizedPath, '../')
|
||||
|| str_contains($normalizedPath, '/..')
|
||||
|| str_ends_with($normalizedPath, '/..')
|
||||
|| $normalizedPath === '..';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Models\CheckoutAcceptance;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class AcceptSignatureRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
$acceptance = $this->route('acceptance');
|
||||
$user = Auth::user();
|
||||
|
||||
if (! $acceptance || ! $user) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_string($acceptance)) {
|
||||
$acceptance = CheckoutAcceptance::find($acceptance);
|
||||
if (! $acceptance) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (! $user instanceof User) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only allow if the user is the assigned user or sign-in-place admin
|
||||
$assignedToId = $acceptance->assigned_to_id ?? null;
|
||||
$isSignInPlaceAdmin = session('sign_in_place_acceptance_id') === $acceptance->id && $user->can('checkout', $acceptance->checkoutable);
|
||||
|
||||
return $user->id === $assignedToId || $isSignInPlaceAdmin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
// ...existing validation rules...
|
||||
];
|
||||
}
|
||||
|
||||
protected function failedAuthorization()
|
||||
{
|
||||
$user = Auth::user();
|
||||
$acceptance = $this->route('acceptance');
|
||||
// If user is logged in and acceptance exists, treat as business logic error
|
||||
if ($user && $acceptance) {
|
||||
$redirectResponse = redirect()->route('account.accept')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
|
||||
throw new ValidationException($this->getValidatorInstance(), $redirectResponse);
|
||||
}
|
||||
// Otherwise, use default 403
|
||||
parent::failedAuthorization();
|
||||
}
|
||||
}
|
||||
@@ -57,6 +57,7 @@ class ImageUploadRequest extends Request
|
||||
* had it once to allow encoded image uploads.
|
||||
*/
|
||||
return [
|
||||
'avatar' => 'auto',
|
||||
'image' => 'auto',
|
||||
'image_source' => 'auto',
|
||||
];
|
||||
|
||||
@@ -51,7 +51,7 @@ class CategoriesTransformer
|
||||
'name' => e($category->name),
|
||||
'image' => ($category->image) ? Storage::disk('public')->url('categories/'.e($category->image)) : null,
|
||||
'category_type' => Helper::categoryTypeList($category->category_type),
|
||||
'has_eula' => ($category->getEula() ? true : false),
|
||||
'has_eula' => ($category->eula_text) ? true : false,
|
||||
'use_default_eula' => ($category->use_default_eula == '1' ? true : false),
|
||||
'eula' => ($category->getEula()),
|
||||
'checkin_email' => ($category->checkin_email == '1'),
|
||||
|
||||
@@ -78,7 +78,7 @@ class CheckoutableListener
|
||||
$acceptance = $this->getCheckoutAcceptance($event);
|
||||
|
||||
$shouldSendEmailToUser = $this->shouldSendCheckoutEmailToUser($event->checkoutable);
|
||||
$shouldSendEmailToAlertAddress = $this->shouldSendEmailToAlertAddress($acceptance);
|
||||
$shouldSendEmailToAlertAddress = $this->shouldSendEmailToAlertAddress($acceptance, $event->checkoutable);
|
||||
$shouldSendWebhookNotification = $this->shouldSendWebhookNotification();
|
||||
|
||||
if ($this->shouldSkipInitialAcceptanceEmail($event, $acceptance)) {
|
||||
@@ -175,7 +175,7 @@ class CheckoutableListener
|
||||
}
|
||||
|
||||
$shouldSendEmailToUser = $this->checkoutableCategoryShouldSendEmail($event->checkoutable);
|
||||
$shouldSendEmailToAlertAddress = $this->shouldSendEmailToAlertAddress();
|
||||
$shouldSendEmailToAlertAddress = $this->shouldSendEmailToAlertAddress(null, $event->checkoutable);
|
||||
$shouldSendWebhookNotification = $this->shouldSendWebhookNotification();
|
||||
if (! $shouldSendEmailToUser && ! $shouldSendEmailToAlertAddress && ! $shouldSendWebhookNotification) {
|
||||
return;
|
||||
@@ -198,33 +198,39 @@ class CheckoutableListener
|
||||
}
|
||||
|
||||
$mailable = $this->getCheckinMailType($event);
|
||||
$notifiable = $this->getNotifiableUser($event);
|
||||
|
||||
$notifiableHasEmail = $notifiable instanceof User && $notifiable->email;
|
||||
if (! $mailable) {
|
||||
Log::debug('No checkin mail type available for checkoutable class: '.get_class($event->checkoutable));
|
||||
} else {
|
||||
$notifiable = $this->getNotifiableUser($event);
|
||||
|
||||
$shouldSendEmailToUser = $shouldSendEmailToUser && $notifiableHasEmail;
|
||||
$notifiableHasEmail = $notifiable instanceof User && $notifiable->email;
|
||||
|
||||
[$to, $cc] = $this->generateEmailRecipients($shouldSendEmailToUser, $shouldSendEmailToAlertAddress, $notifiable);
|
||||
$shouldSendEmailToUser = $shouldSendEmailToUser && $notifiableHasEmail;
|
||||
|
||||
if (! empty($to)) {
|
||||
try {
|
||||
$toMail = (clone $mailable)->locale($notifiable->locale);
|
||||
Mail::to(array_flatten($to))->send($toMail);
|
||||
Log::info('Checkin Mail sent to checkin target');
|
||||
} catch (ClientException $e) {
|
||||
Log::debug('Exception caught during checkin email: '.$e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
Log::debug('Exception caught during checkin email: '.$e->getMessage());
|
||||
[$to, $cc] = $this->generateEmailRecipients($shouldSendEmailToUser, $shouldSendEmailToAlertAddress, $notifiable);
|
||||
|
||||
if (! empty($to)) {
|
||||
try {
|
||||
$toMail = (clone $mailable)->locale($notifiable->locale);
|
||||
Mail::to(array_flatten($to))->send($toMail);
|
||||
Log::info('Checkin Mail sent to checkin target');
|
||||
} catch (ClientException $e) {
|
||||
Log::debug('Exception caught during checkin email: '.$e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
Log::debug('Exception caught during checkin email: '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! empty($cc)) {
|
||||
try {
|
||||
$ccMail = (clone $mailable)->locale(Setting::getSettings()->locale);
|
||||
Mail::cc(array_flatten($cc))->send($ccMail);
|
||||
} catch (ClientException $e) {
|
||||
Log::debug('Exception caught during checkin email: '.$e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
Log::debug('Exception caught during checkin email: '.$e->getMessage());
|
||||
|
||||
if (! empty($cc)) {
|
||||
try {
|
||||
$ccMail = (clone $mailable)->locale(Setting::getSettings()->locale);
|
||||
Mail::cc(array_flatten($cc))->send($ccMail);
|
||||
} catch (ClientException $e) {
|
||||
Log::debug('Exception caught during checkin email: '.$e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
Log::debug('Exception caught during checkin email: '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -392,7 +398,14 @@ class CheckoutableListener
|
||||
LicenseSeat::class => CheckinLicenseMail::class,
|
||||
Component::class => CheckinComponentMail::class,
|
||||
];
|
||||
$mailable = $lookup[get_class($event->checkoutable)];
|
||||
|
||||
$checkoutableClass = get_class($event->checkoutable);
|
||||
|
||||
if (! array_key_exists($checkoutableClass, $lookup)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$mailable = $lookup[$checkoutableClass];
|
||||
|
||||
return new $mailable($event->checkoutable, $event->checkedOutTo, $event->checkedInBy, $event->note);
|
||||
|
||||
@@ -466,11 +479,16 @@ class CheckoutableListener
|
||||
* 1. The asset requires acceptance
|
||||
* 2. The item has a EULA
|
||||
* 3. The item should send an email at check-in/check-out
|
||||
* 4. The config('app.always_send_email') is true
|
||||
*/
|
||||
if (Context::get('action') === 'bulk_asset_checkout') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (config('app.always_send_email')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($checkoutable->requireAcceptance()) {
|
||||
return true;
|
||||
}
|
||||
@@ -495,7 +513,7 @@ class CheckoutableListener
|
||||
return ($acceptance instanceof CheckoutAcceptance) || ! empty($event->checkoutable->getEula());
|
||||
}
|
||||
|
||||
private function shouldSendEmailToAlertAddress($acceptance = null): bool
|
||||
private function shouldSendEmailToAlertAddress($acceptance = null, ?Model $checkoutable = null): bool
|
||||
{
|
||||
if (Context::get('action') === 'bulk_asset_checkout') {
|
||||
return false;
|
||||
@@ -507,22 +525,39 @@ class CheckoutableListener
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_null($acceptance) && ! $setting->admin_cc_always) {
|
||||
$alertRecipients = $this->getFormattedAlertAddresses((bool) $setting->admin_cc_always);
|
||||
|
||||
if (empty($alertRecipients)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (bool) $setting->admin_cc_email;
|
||||
}
|
||||
|
||||
private function getFormattedAlertAddresses(): array
|
||||
{
|
||||
$alertAddresses = Setting::getSettings()->admin_cc_email;
|
||||
|
||||
if ($alertAddresses !== '') {
|
||||
return array_filter(array_map('trim', explode(',', $alertAddresses)));
|
||||
if (is_null($acceptance) && ! $setting->admin_cc_always) {
|
||||
if (! $checkoutable || ! $this->checkoutableCategoryShouldSendEmail($checkoutable)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getFormattedAlertAddresses(bool $allowAlertEmailFallback = false): array
|
||||
{
|
||||
$setting = Setting::getSettings();
|
||||
|
||||
if (! $setting) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$adminCcAddresses = $setting->admin_cc_email;
|
||||
$fallbackAlertAddresses = $allowAlertEmailFallback ? $setting->alert_email : null;
|
||||
|
||||
$rawAddresses = $adminCcAddresses ?: $fallbackAlertAddresses;
|
||||
|
||||
if ($rawAddresses === null || $rawAddresses === '') {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_values(array_unique(array_filter(array_map('trim', explode(',', $rawAddresses)))));
|
||||
}
|
||||
|
||||
private function generateEmailRecipients(
|
||||
@@ -536,7 +571,7 @@ class CheckoutableListener
|
||||
// if user && cc: to user, cc admin
|
||||
if ($shouldSendEmailToUser && $shouldSendEmailToAlertAddress) {
|
||||
$to[] = $notifiable;
|
||||
$cc[] = $this->getFormattedAlertAddresses();
|
||||
$cc[] = $this->getFormattedAlertAddresses(true);
|
||||
}
|
||||
|
||||
// if user && no cc: to user
|
||||
@@ -546,7 +581,7 @@ class CheckoutableListener
|
||||
|
||||
// if no user && cc: to admin
|
||||
if (! $shouldSendEmailToUser && $shouldSendEmailToAlertAddress) {
|
||||
$to[] = $this->getFormattedAlertAddresses();
|
||||
$to[] = $this->getFormattedAlertAddresses(true);
|
||||
}
|
||||
|
||||
return [$to, $cc];
|
||||
|
||||
@@ -10,6 +10,7 @@ use App\Events\UserMerged;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\LicenseSeat;
|
||||
use App\Models\User;
|
||||
use Illuminate\Events\Dispatcher;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class LogListener
|
||||
@@ -59,7 +60,10 @@ class LogListener
|
||||
$logaction->action_type = 'accepted';
|
||||
$logaction->action_date = $event->acceptance->accepted_at;
|
||||
$logaction->quantity = $event->acceptance->qty ?? 1;
|
||||
$logaction->created_by = auth()->user()->id;
|
||||
$logaction->created_by = auth()->user()?->getAuthIdentifier();
|
||||
$logaction->remote_ip = request()->ip();
|
||||
$logaction->user_agent = request()->header('User-Agent');
|
||||
$logaction->action_source = 'gui';
|
||||
|
||||
// TODO: log the actual license seat that was checked out
|
||||
if ($event->acceptance->checkoutable instanceof LicenseSeat) {
|
||||
@@ -79,7 +83,10 @@ class LogListener
|
||||
$logaction->action_type = 'declined';
|
||||
$logaction->action_date = $event->acceptance->declined_at;
|
||||
$logaction->quantity = $event->acceptance->qty ?? 1;
|
||||
$logaction->created_by = auth()->user()->id;
|
||||
$logaction->created_by = auth()->user()?->getAuthIdentifier();
|
||||
$logaction->remote_ip = request()->ip();
|
||||
$logaction->user_agent = request()->header('User-Agent');
|
||||
$logaction->action_source = 'gui';
|
||||
|
||||
// TODO: log the actual license seat that was checked out
|
||||
if ($event->acceptance->checkoutable instanceof LicenseSeat) {
|
||||
@@ -127,7 +134,7 @@ class LogListener
|
||||
/**
|
||||
* Register the listeners for the subscriber.
|
||||
*
|
||||
* @param Illuminate\Events\Dispatcher $events
|
||||
* @param Dispatcher $events
|
||||
*/
|
||||
public function subscribe($events)
|
||||
{
|
||||
|
||||
@@ -1267,6 +1267,38 @@ class Asset extends Depreciable
|
||||
return (float) $this->components->sum('calculated_purchase_cost');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return EOL progress percentage (0-100), based on elapsed months since
|
||||
* purchase date over the configured EOL window.
|
||||
*/
|
||||
public function eolProgressPercent(): float
|
||||
{
|
||||
if (! $this->purchase_date || ! $this->asset_eol_date) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return $this->calculateProgressPercent(
|
||||
start: Carbon::parse($this->purchase_date),
|
||||
end: Carbon::parse($this->asset_eol_date),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return warranty progress percentage (0-100), based on elapsed months
|
||||
* since purchase date over the warranty window.
|
||||
*/
|
||||
public function warrantyProgressPercent(): float
|
||||
{
|
||||
if (! $this->purchase_date || ! $this->warranty_expires) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return $this->calculateProgressPercent(
|
||||
start: Carbon::parse($this->purchase_date),
|
||||
end: $this->warranty_expires,
|
||||
);
|
||||
}
|
||||
|
||||
public function getAccessoryCost()
|
||||
{
|
||||
return (float) $this->accessories()->sum('purchase_cost');
|
||||
@@ -2134,4 +2166,16 @@ class Asset extends Depreciable
|
||||
->join('depreciations', 'models.depreciation_id', '=', 'depreciations.id')->where('models.depreciation_id', '=', $search);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the asset has an orphaned assignment where the assigned target no longer exists.
|
||||
* This occurs when:
|
||||
* 1. assigned_to is set but assigned_type is missing/null
|
||||
* 2. assigned_to and assigned_type are both set, but the relationship cannot be resolved (target was hard-deleted)
|
||||
*/
|
||||
public function hasOrphanedAssignment(): bool
|
||||
{
|
||||
return ($this->assigned_to && ! $this->assigned_type)
|
||||
|| ($this->assigned_to && $this->assigned_type && ! $this->assignedTo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,21 @@ class CheckoutAcceptance extends Model
|
||||
'alert_on_response_id' => 'integer',
|
||||
];
|
||||
|
||||
protected $fillable = [
|
||||
'assigned_to_id',
|
||||
'checkoutable_type',
|
||||
'checkoutable_id',
|
||||
'accepted_at',
|
||||
'declined_at',
|
||||
'note',
|
||||
'signature_filename',
|
||||
'stored_eula',
|
||||
'stored_eula_file',
|
||||
'qty',
|
||||
'signed_in_place',
|
||||
'signed_in_place_admin',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the mail recipient from the config
|
||||
*
|
||||
@@ -112,7 +127,7 @@ class CheckoutAcceptance extends Model
|
||||
*/
|
||||
public function isCheckedOutTo(User $user)
|
||||
{
|
||||
return $this->assignedTo?->is($user);
|
||||
return $this->assigned_to_id === $user->id;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,20 +136,27 @@ class CheckoutAcceptance extends Model
|
||||
* checkout_acceptances table or you'll get an error.
|
||||
*
|
||||
* @param string $signature_filename
|
||||
* @param string|null $eula
|
||||
* @param string|null $filename
|
||||
* @param string|null $note
|
||||
* @param int|null $qty
|
||||
*/
|
||||
public function accept($signature_filename, $eula = null, $filename = null, $note = null)
|
||||
public function accept($signature_filename, $eula = null, $filename = null, $note = null, $qty = null)
|
||||
{
|
||||
$this->accepted_at = now();
|
||||
$this->signature_filename = $signature_filename;
|
||||
$this->stored_eula = $eula;
|
||||
$this->stored_eula_file = $filename;
|
||||
$this->note = $note;
|
||||
if ($qty !== null) {
|
||||
$this->qty = $qty;
|
||||
}
|
||||
$this->save();
|
||||
|
||||
/**
|
||||
* Update state for the checked out item
|
||||
*/
|
||||
$this->checkoutable->acceptedCheckout($this->assignedTo, $signature_filename, $filename);
|
||||
$this->checkoutable->acceptedCheckout($this->assignedTo, $qty, $note, $signature_filename, $filename);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,7 +230,7 @@ class CheckoutAcceptance extends Model
|
||||
$pdf->SetAuthor($data['assigned_to']);
|
||||
$pdf->SetTitle('Asset Acceptance: '.$data['item_tag']);
|
||||
$pdf->SetSubject('Asset Acceptance: '.$data['item_tag']);
|
||||
$pdf->SetKeywords('Snipe-IT, assets, acceptance, eula, tos');
|
||||
$pdf->SetKeywords('Snipe-IT, assets, acceptance, eula, tos,'.$data['item_tag'] ?? null.', '.$data['item_name'] ?? null.', '.$data['assigned_to'] ?? null);
|
||||
$pdf->SetFont('dejavusans', '', 8, '', true);
|
||||
$pdf->SetPrintHeader(false);
|
||||
$pdf->SetPrintFooter(false);
|
||||
@@ -243,6 +265,17 @@ class CheckoutAcceptance extends Model
|
||||
if ($data['item_serial'] != null) {
|
||||
$pdf->writeHTML(trans('admin/hardware/form.serial').': '.e($data['item_serial']), true, 0, true, 0, '');
|
||||
}
|
||||
// Render custom fields if present
|
||||
if (! empty($data['custom_fields']) && is_array($data['custom_fields'])) {
|
||||
foreach ($data['custom_fields'] as $customField) {
|
||||
$label = $customField['label'] ?? '';
|
||||
$value = $customField['value'] ?? '';
|
||||
if ($label !== '' && $value !== '') {
|
||||
$pdf->writeHTML(e($label).': '.e($value), true, 0, true, 0, '');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (($data['qty'] != null) && ($data['qty'] > 1)) {
|
||||
$pdf->writeHTML(trans('general.qty').': '.e($data['qty']), true, 0, true, 0, '');
|
||||
}
|
||||
@@ -250,6 +283,35 @@ class CheckoutAcceptance extends Model
|
||||
if ($data['email'] != null) {
|
||||
$pdf->writeHTML(trans('general.email').': '.e($data['email']), true, 0, true, 0, '');
|
||||
}
|
||||
// Add assigning user if present
|
||||
if (! empty($data['assigning_user'])) {
|
||||
$assigningUser = $data['assigning_user'];
|
||||
$assigningUserLine = trans('general.assigned_by').': '.e($assigningUser['name'] ?? $assigningUser['email'] ?? '');
|
||||
if (! empty($assigningUser['employee_num'])) {
|
||||
$assigningUserLine .= ' ('.e($assigningUser['employee_num']).')';
|
||||
}
|
||||
$pdf->writeHTML($assigningUserLine, true, 0, true, 0, '');
|
||||
}
|
||||
// Add signed in place row (always show)
|
||||
$signedInPlace = ! empty($data['signed_in_place']) && filter_var($data['signed_in_place'], FILTER_VALIDATE_BOOLEAN);
|
||||
$pdf->writeHTML(trans('general.signed_in_place').': '.($signedInPlace ? trans('general.yes') : trans('general.no')), true, 0, true, 0, '');
|
||||
// If signed in place, show admin info
|
||||
if ($signedInPlace && ! empty($data['signed_in_place_admin'])) {
|
||||
$admin = $data['signed_in_place_admin'];
|
||||
$adminName = $admin['name'] ?? '';
|
||||
$adminUsername = $admin['username'] ?? '';
|
||||
$adminEmail = $admin['email'] ?? '';
|
||||
$adminDetails = $adminName;
|
||||
if (! empty($adminUsername)) {
|
||||
$adminDetails .= ' ('.$adminUsername.')';
|
||||
}
|
||||
if (! empty($adminEmail)) {
|
||||
$adminDetails .= ' <'.$adminEmail.'>';
|
||||
}
|
||||
$adminLine = trans('general.signed_in_place_admin', ['admin' => $adminDetails]);
|
||||
$pdf->writeHTML($adminLine, true, 0, true, 0, '');
|
||||
}
|
||||
|
||||
$pdf->Ln();
|
||||
$pdf->writeHTML('<hr>', true, 0, true, 0, '');
|
||||
|
||||
|
||||
@@ -495,4 +495,83 @@ class Consumable extends SnipeModel
|
||||
{
|
||||
return $query->leftJoin('users as users_sort', 'consumables.created_by', '=', 'users_sort.id')->select('consumables.*')->orderBy('users_sort.first_name', $order)->orderBy('users_sort.last_name', $order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle logic after a consumable checkout is accepted by the user.
|
||||
*
|
||||
* @param string|null $signature
|
||||
* @param string|null $filename
|
||||
*/
|
||||
public function acceptedCheckout(User $acceptedBy, ?int $qty = null, ?string $note = null, $signature = null, $filename = null): void
|
||||
{
|
||||
// Find the pending acceptance for this user and consumable
|
||||
$acceptance = $acceptedBy->getAssignedItemsWithPendingAcceptance()
|
||||
->where('item_id', $this->id)
|
||||
->where('qty', $qty)
|
||||
->where('item_type', self::class)
|
||||
->whereNull('declined_at')
|
||||
->sortByDesc('created_at')
|
||||
->first();
|
||||
|
||||
if ($acceptance) {
|
||||
if ($qty !== null) {
|
||||
$acceptance->qty = $qty;
|
||||
}
|
||||
if ($note !== null) {
|
||||
$acceptance->note = $note;
|
||||
}
|
||||
$acceptance->save();
|
||||
}
|
||||
|
||||
// Attach the consumable to the user if not already attached
|
||||
$pivot = $acceptedBy->consumables()->where('consumable_id', $this->id)->first();
|
||||
if (! $pivot) {
|
||||
$acceptedBy->consumables()->attach($this->id, [
|
||||
'created_by' => $acceptance?->created_by ?? null,
|
||||
]);
|
||||
}
|
||||
|
||||
// Logging handled by event listener; do not log here to avoid duplicates.
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle logic after a consumable checkout is declined by the user.
|
||||
*
|
||||
* @param string|null $signature
|
||||
*/
|
||||
public function declinedCheckout(User $declinedBy, $signature = null): void
|
||||
{
|
||||
// Find the pending acceptance for this user and consumable
|
||||
$acceptance = $declinedBy->acceptances()
|
||||
->where('item_id', $this->id)
|
||||
->where('item_type', self::class)
|
||||
->whereNull('accepted_at')
|
||||
->latest('created_at')
|
||||
->first();
|
||||
|
||||
$qty = $acceptance?->qty ?? 1;
|
||||
$note = $acceptance?->note;
|
||||
|
||||
// Detach the consumable from the user (if present)
|
||||
$declinedBy->consumables()->detach($this->id);
|
||||
|
||||
// Logging handled by event listener; do not log here to avoid duplicates.
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an acceptance or decline action for this consumable.
|
||||
*/
|
||||
protected function logActionAcceptance(string $actionType, User $user, int $qty, ?string $note = null): void
|
||||
{
|
||||
$this->assetlog()->create([
|
||||
'action_type' => $actionType,
|
||||
'target_id' => $user->id,
|
||||
'target_type' => User::class,
|
||||
'item_id' => $this->id,
|
||||
'item_type' => self::class,
|
||||
'quantity' => $qty,
|
||||
'note' => $note,
|
||||
'created_by' => auth()->id() ?? $user->id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
class Depreciable extends SnipeModel
|
||||
{
|
||||
/**
|
||||
@@ -187,6 +189,39 @@ class Depreciable extends SnipeModel
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return depreciation progress percentage (0-100), based on elapsed months
|
||||
* since purchase date over the depreciation window.
|
||||
*/
|
||||
public function depreciationProgressPercent(): float
|
||||
{
|
||||
if (! $this->purchase_date || ! $this->depreciated_date()) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return $this->calculateProgressPercent(
|
||||
start: Carbon::parse($this->purchase_date),
|
||||
end: Carbon::instance($this->depreciated_date()),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate elapsed/total month percentage and clamp to 0-100.
|
||||
*/
|
||||
protected function calculateProgressPercent(Carbon $start, Carbon $end): float
|
||||
{
|
||||
$totalMonths = (float) $start->diffInMonths($end);
|
||||
|
||||
if ($totalMonths <= 0) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
$elapsedMonths = (float) $start->diffInMonths(Carbon::now());
|
||||
$rawPercent = ($elapsedMonths / $totalMonths) * 100;
|
||||
|
||||
return (float) min(100, max(0, $rawPercent));
|
||||
}
|
||||
|
||||
// it's necessary for unit tests
|
||||
protected function getDateTime($time = null)
|
||||
{
|
||||
|
||||
@@ -68,17 +68,8 @@ class DefaultLabel extends RectangleSheet
|
||||
$usableWidth = $this->pageWidth - $this->pageMarginLeft - $this->pageMarginRight;
|
||||
$usableHeight = $this->pageHeight - $this->pageMarginTop - $this->pageMarginBottom;
|
||||
|
||||
$this->columns = ($usableWidth + $this->labelSpacingH) / ($this->labelWidth + $this->labelSpacingH);
|
||||
$this->rows = ($usableHeight + $this->labelSpacingV) / ($this->labelHeight + $this->labelSpacingV);
|
||||
|
||||
// Make sure the columns and rows are never zero, since that scenario should never happen
|
||||
if ($this->columns == 0) {
|
||||
$this->columns = 1;
|
||||
}
|
||||
|
||||
if ($this->rows == 0) {
|
||||
$this->rows = 1;
|
||||
}
|
||||
$this->columns = $this->calculateGridCount($usableWidth, $this->labelWidth, $this->labelSpacingH);
|
||||
$this->rows = $this->calculateGridCount($usableHeight, $this->labelHeight, $this->labelSpacingV);
|
||||
|
||||
}
|
||||
|
||||
@@ -299,4 +290,17 @@ class DefaultLabel extends RectangleSheet
|
||||
|
||||
return $labelHeight;
|
||||
}
|
||||
|
||||
private function calculateGridCount(float $usableSize, float $labelSize, float $spacing): int
|
||||
{
|
||||
$denominator = $labelSize + $spacing;
|
||||
|
||||
if ($denominator <= 0.0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
$count = (int) floor(($usableSize + $spacing) / $denominator);
|
||||
|
||||
return max(1, $count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,6 +303,32 @@ trait Loggable
|
||||
return $log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a force checkin action for orphaned assignments.
|
||||
*
|
||||
* Force checkin only records an explicit action log entry and intentionally
|
||||
* skips checkin counters and changed-field metadata.
|
||||
*
|
||||
* @return Actionlog
|
||||
*/
|
||||
public function logForceCheckin($note = null)
|
||||
{
|
||||
$log = new Actionlog;
|
||||
|
||||
$log = $this->determineLogItemType($log);
|
||||
$log->location_id = null;
|
||||
$log->note = $note;
|
||||
$log->action_date = date('Y-m-d H:i:s');
|
||||
|
||||
if (auth()->user()) {
|
||||
$log->created_by = auth()->id();
|
||||
}
|
||||
|
||||
$log->logaction('force checkin');
|
||||
|
||||
return $log;
|
||||
}
|
||||
|
||||
/**
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
*
|
||||
|
||||
@@ -33,6 +33,9 @@ class AcceptanceItemAcceptedNotification extends Notification
|
||||
$this->file = $params['file'] ?? null;
|
||||
$this->qty = $params['qty'] ?? null;
|
||||
$this->note = $params['note'] ?? null;
|
||||
$this->signed_in_place = $params['signed_in_place'] ?? false;
|
||||
$this->signed_in_place_admin = $params['signed_in_place_admin'] ?? null;
|
||||
$this->custom_fields = $params['custom_fields'] ?? [];
|
||||
|
||||
}
|
||||
|
||||
@@ -76,6 +79,9 @@ class AcceptanceItemAcceptedNotification extends Notification
|
||||
'assigned_to' => $this->assigned_to,
|
||||
'company_name' => $this->company_name,
|
||||
'qty' => $this->qty,
|
||||
'signed_in_place' => $this->signed_in_place,
|
||||
'signed_in_place_admin' => $this->signed_in_place_admin,
|
||||
'custom_fields' => $this->custom_fields,
|
||||
'intro_text' => trans('mail.acceptance_accepted_greeting', ['user' => $this->assigned_to, 'item' => $this->item_name]),
|
||||
])
|
||||
->subject('✅ '.trans('mail.acceptance_accepted', ['user' => $this->assigned_to, 'item' => $this->item_name]))
|
||||
|
||||
@@ -34,6 +34,7 @@ class AcceptanceItemAcceptedToUserNotification extends Notification
|
||||
$this->settings = Setting::getSettings();
|
||||
$this->file = $params['file'] ?? null;
|
||||
$this->qty = $params['qty'] ?? null;
|
||||
$this->custom_fields = $params['custom_fields'] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,6 +73,7 @@ class AcceptanceItemAcceptedToUserNotification extends Notification
|
||||
'assigned_to' => $this->assigned_to,
|
||||
'company_name' => $this->company_name,
|
||||
'qty' => $this->qty,
|
||||
'custom_fields' => $this->custom_fields,
|
||||
'intro_text' => trans_choice('mail.acceptance_asset_accepted_to_user', $this->qty, ['qty' => $this->qty, 'site_name' => $this->settings->site_name]),
|
||||
])
|
||||
->attach($pdf_path)
|
||||
|
||||
@@ -32,6 +32,7 @@ class AcceptanceItemDeclinedNotification extends Notification
|
||||
$this->settings = Setting::getSettings();
|
||||
$this->qty = $params['qty'] ?? null;
|
||||
$this->admin = $params['admin'] ?? null;
|
||||
$this->custom_fields = $params['custom_fields'] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,6 +75,7 @@ class AcceptanceItemDeclinedNotification extends Notification
|
||||
'company_name' => $this->company_name,
|
||||
'qty' => $this->qty,
|
||||
'admin' => $this->admin,
|
||||
'custom_fields' => $this->custom_fields,
|
||||
'user' => $this->assigned_to,
|
||||
'intro_text' => trans('mail.acceptance_declined_greeting', ['user' => $this->assigned_to]),
|
||||
])
|
||||
|
||||
@@ -59,10 +59,18 @@ class CategoryPresenter extends Presenter
|
||||
], [
|
||||
'field' => 'has_eula',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'sortable' => true,
|
||||
'title' => trans('admin/categories/table.eula_text'),
|
||||
'visible' => false,
|
||||
'formatter' => 'trueFalseFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'use_default_eula',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'title' => trans('admin/settings/general.default_eula_text'),
|
||||
'visible' => false,
|
||||
'formatter' => 'trueFalseFormatter',
|
||||
], [
|
||||
'field' => 'checkin_email',
|
||||
'searchable' => false,
|
||||
@@ -78,13 +86,6 @@ class CategoryPresenter extends Presenter
|
||||
'title' => trans('admin/categories/table.require_acceptance'),
|
||||
'visible' => true,
|
||||
'formatter' => 'trueFalseFormatter',
|
||||
], [
|
||||
'field' => 'use_default_eula',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'title' => trans('admin/categories/general.use_default_eula_column'),
|
||||
'visible' => true,
|
||||
'formatter' => 'trueFalseFormatter',
|
||||
], [
|
||||
'field' => 'tag_color',
|
||||
'searchable' => true,
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace App\Presenters;
|
||||
|
||||
use App\Models\CustomField;
|
||||
|
||||
/**
|
||||
* Class CustomFieldPresenter
|
||||
* Handles presentation logic for CustomField, including visibility icons.
|
||||
*/
|
||||
final class CustomFieldPresenter extends Presenter
|
||||
{
|
||||
private CustomField $field;
|
||||
|
||||
public function __construct(CustomField $field)
|
||||
{
|
||||
$this->field = $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of icon HTML for where the field is visible.
|
||||
*
|
||||
* @return string[] Array of HTML icon strings
|
||||
*/
|
||||
public function visibilityIconsArray(): array
|
||||
{
|
||||
$icons = [];
|
||||
if ($this->field->display_checkout) {
|
||||
$icons[] = '<span title="'.e(trans('admin/custom_fields/general.display_checkout')).'" data-tooltip="true"><i class="fa-solid fa-rotate-left text-muted"></i></span>';
|
||||
}
|
||||
if ($this->field->display_checkin) {
|
||||
$icons[] = '<span title="'.e(trans('admin/custom_fields/general.display_checkin')).'" data-tooltip="true"><i class="fa-solid fa-rotate-right text-muted"></i></span>';
|
||||
}
|
||||
if ($this->field->display_audit) {
|
||||
$icons[] = '<span title="'.e(trans('admin/custom_fields/general.display_audit')).'" data-tooltip="true"><i class="fas fa-clipboard-check text-muted"></i></span>';
|
||||
}
|
||||
if ($this->field->display_in_user_view) {
|
||||
$icons[] = '<span title="'.e(trans('admin/custom_fields/general.display_in_user_view_table')).'" data-tooltip="true"><i class="fas fa-user text-muted"></i></span>';
|
||||
}
|
||||
if ($this->field->show_in_listview) {
|
||||
$icons[] = '<span title="'.e(trans('admin/custom_fields/general.show_in_listview_short')).'" data-tooltip="true"><i class="fas fa-list text-muted"></i></span>';
|
||||
}
|
||||
if ($this->field->show_in_email) {
|
||||
$icons[] = '<span title="'.e(trans('admin/custom_fields/general.show_in_email_short')).'" data-tooltip="true"><i class="fas fa-envelope text-muted"></i></span>';
|
||||
}
|
||||
if ($this->field->show_in_requestable_list) {
|
||||
$icons[] = '<span title="'.e(trans('admin/custom_fields/general.show_in_requestable_list_short')).'" data-tooltip="true"><i class="fa-solid fa-bell-concierge text-muted"></i></span>';
|
||||
}
|
||||
|
||||
return $icons;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the icons as a single HTML string (for backward compatibility)
|
||||
*/
|
||||
public function visibilityIcons(): string
|
||||
{
|
||||
return implode(' ', $this->visibilityIconsArray());
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -110,7 +110,7 @@ class Label implements View
|
||||
$logo = Storage::disk('public')->path('companies/'.e($asset->company->image));
|
||||
} elseif (! empty($settings->label_logo)) {
|
||||
// Use the general site label logo, if available
|
||||
$logo = Storage::disk('public')->path('/'.e($settings->label_logo));
|
||||
$logo = Storage::disk('public')->path('/'.e(basename($settings->label_logo)));
|
||||
} elseif (! empty($asset->is_label_preview)) {
|
||||
$logo = public_path('img/label-preview-logo.png');
|
||||
}
|
||||
|
||||
@@ -537,4 +537,21 @@ return [
|
||||
|
||||
'max_unpaginated_records' => env('MAX_UNPAGINATED', '5000'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Always send emails on acceptance/EULA
|
||||
|--------------------------------------------------------------------------
|
||||
| This setting allows you to bypass the "email me a copy" checkbox on EULA/item acceptance,
|
||||
| and forces Snipe-IT to always send email to the accepting user if they have an email address.
|
||||
*/
|
||||
'always_send_email' => env('ALWAYS_SEND_EMAIL', false),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Always Send EULA
|
||||
|--------------------------------------------------------------------------
|
||||
| If true, the EULA will always be sent and the checkbox will be hidden.
|
||||
*/
|
||||
'always_send_eula' => env('ALWAYS_SEND_EULA', false),
|
||||
|
||||
];
|
||||
|
||||
+7
@@ -18,6 +18,13 @@ class DenormalizedEolAndAddColumnForExplicitDateToAssets extends Migration
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
|
||||
Schema::table('companies', function (Blueprint $table) {
|
||||
if (! Schema::hasColumn('companies', 'deleted_at')) {
|
||||
$table->softDeletes();
|
||||
}
|
||||
});
|
||||
|
||||
Schema::table('assets', function (Blueprint $table) {
|
||||
if (! Schema::hasColumn('assets', 'eol_explicit')) {
|
||||
$table->boolean('eol_explicit')->default(false)->after('asset_eol_date');
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('consumables_users', function (Blueprint $table) {
|
||||
$table->unsignedInteger('qty')->nullable()->default(1)->after('created_by');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('consumables_users', function (Blueprint $table) {
|
||||
$table->dropColumn('qty');
|
||||
});
|
||||
}
|
||||
};
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('checkout_acceptances', function (Blueprint $table) {
|
||||
$table->boolean('signed_in_place')->default(false)->after('declined_at');
|
||||
$table->unsignedBigInteger('signed_in_place_admin')->nullable()->after('signed_in_place');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('checkout_acceptances', function (Blueprint $table) {
|
||||
$table->dropColumn(['signed_in_place', 'signed_in_place_admin']);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -9,7 +9,7 @@ return [
|
||||
'edit' => 'crwdns1606:0crwdne1606:0',
|
||||
'eula_text' => 'crwdns1210:0crwdne1210:0',
|
||||
'eula_text_help' => 'crwdns1211:0crwdne1211:0',
|
||||
'require_acceptance' => 'crwdns1212:0crwdne1212:0',
|
||||
'require_acceptance' => 'crwdns14698:0crwdne14698:0',
|
||||
'no_default_eula' => 'crwdns1213:0crwdne1213:0',
|
||||
'total' => 'crwdns1215:0crwdne1215:0',
|
||||
'remaining' => 'crwdns1216:0crwdne1216:0',
|
||||
|
||||
@@ -17,6 +17,7 @@ return [
|
||||
'name' => 'crwdns1835:0crwdne1835:0',
|
||||
'require_acceptance' => 'crwdns1243:0crwdne1243:0',
|
||||
'required_acceptance' => 'crwdns1244:0crwdne1244:0',
|
||||
'global_signature_required_notice' => 'crwdns14708:0crwdne14708:0',
|
||||
'required_eula' => 'crwdns1245:0crwdne1245:0',
|
||||
'no_default_eula' => 'crwdns1246:0crwdne1246:0',
|
||||
'update' => 'crwdns639:0crwdne639:0',
|
||||
|
||||
@@ -5,7 +5,7 @@ return [
|
||||
'manage' => 'crwdns6501:0crwdne6501:0',
|
||||
'field' => 'crwdns1487:0crwdne1487:0',
|
||||
'about_fieldsets_title' => 'crwdns1488:0crwdne1488:0',
|
||||
'about_fieldsets_text' => 'crwdns14508:0crwdne14508:0',
|
||||
'about_fieldsets_text' => 'crwdns14566:0crwdne14566:0',
|
||||
'custom_format' => 'crwdns6505:0crwdne6505:0',
|
||||
'encrypt_field' => 'crwdns1792:0crwdne1792:0',
|
||||
'encrypt_field_help' => 'crwdns1683:0crwdne1683:0',
|
||||
|
||||
@@ -7,5 +7,6 @@ return [
|
||||
'invalid_return_value' => 'crwdns11719:0crwdne11719:0',
|
||||
|
||||
'does_not_exist' => 'crwdns11721:0crwdne11721:0',
|
||||
|
||||
'use_new_label_engine_for_api' => 'crwdns14722:0crwdne14722:0',
|
||||
'label_not_created' => 'crwdns14724:0crwdne14724:0',
|
||||
];
|
||||
|
||||
@@ -8,7 +8,6 @@ return [
|
||||
'assoc_child_loc' => 'crwdns1405:0crwdne1405:0',
|
||||
'assigned_assets' => 'crwdns11179:0crwdne11179:0',
|
||||
'current_location' => 'crwdns11181:0crwdne11181:0',
|
||||
'open_map' => 'crwdns12696:0crwdne12696:0',
|
||||
'deleted_warning' => 'crwdns13790:0crwdne13790:0',
|
||||
|
||||
'create' => [
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
return [
|
||||
'select_type' => 'crwdns13584:0crwdne13584:0',
|
||||
'asset_maintenance_type' => 'crwdns13586:0crwdne13586:0',
|
||||
'asset_maintenance_type' => 'crwdns14588:0crwdne14588:0',
|
||||
'title' => 'crwdns13588:0crwdne13588:0',
|
||||
'start_date' => 'crwdns13590:0crwdne13590:0',
|
||||
'completion_date' => 'crwdns13592:0crwdne13592:0',
|
||||
'cost' => 'crwdns13594:0crwdne13594:0',
|
||||
'is_warranty' => 'crwdns13596:0crwdne13596:0',
|
||||
'asset_maintenance_time' => 'crwdns13598:0crwdne13598:0',
|
||||
'asset_maintenance_time' => 'crwdns14586:0crwdne14586:0',
|
||||
'notes' => 'crwdns13600:0crwdne13600:0',
|
||||
'update' => 'crwdns13602:0crwdne13602:0',
|
||||
'create' => 'crwdns13604:0crwdne13604:0',
|
||||
|
||||
@@ -309,7 +309,7 @@ return [
|
||||
'two_factor_enabled_edit_not_allowed' => 'crwdns1818:0crwdne1818:0',
|
||||
'two_factor_enrollment_text' => 'crwdns1791:0crwdne1791:0',
|
||||
'require_accept_signature' => 'crwdns1819:0crwdne1819:0',
|
||||
'require_accept_signature_help_text' => 'crwdns1820:0crwdne1820:0',
|
||||
'require_accept_signature_help_text' => 'crwdns14704:0crwdne14704:0',
|
||||
'require_checkinout_notes' => 'crwdns12794:0crwdne12794:0',
|
||||
'require_checkinout_notes_help_text' => 'crwdns12796:0crwdne12796:0',
|
||||
'left' => 'crwdns1597:0crwdne1597:0',
|
||||
@@ -324,15 +324,30 @@ return [
|
||||
'username_format_help' => 'crwdns5918:0crwdne5918:0',
|
||||
'oauth_title' => 'crwdns6403:0crwdne6403:0',
|
||||
'oauth_clients' => 'crwdns12246:0crwdne12246:0',
|
||||
'oauth' => 'crwdns6405:0crwdne6405:0',
|
||||
'oauth_help' => 'crwdns6407:0crwdne6407:0',
|
||||
'oauth' => 'crwdns14658:0crwdne14658:0',
|
||||
'oauth_help' => 'crwdns14660:0crwdne14660:0',
|
||||
'oauth_no_clients' => 'crwdns12248:0crwdne12248:0',
|
||||
'oauth_no_applications' => 'crwdns14662:0crwdne14662:0',
|
||||
'oauth_secret' => 'crwdns12250:0crwdne12250:0',
|
||||
'oauth_authorized_apps' => 'crwdns12252:0crwdne12252:0',
|
||||
'oauth_redirect_url' => 'crwdns12254:0crwdne12254:0',
|
||||
'oauth_name_help' => 'crwdns12256:0crwdne12256:0',
|
||||
'oauth_scopes' => 'crwdns12258:0crwdne12258:0',
|
||||
'oauth_client_type' => 'crwdns14664:0crwdne14664:0',
|
||||
'oauth_client_type_oauth' => 'crwdns14666:0crwdne14666:0',
|
||||
'oauth_client_type_personal_access' => 'crwdns14668:0crwdne14668:0',
|
||||
'oauth_client_type_password_grant' => 'crwdns14670:0crwdne14670:0',
|
||||
'oauth_associated_token_count' => 'crwdns14672:0crwdne14672:0',
|
||||
'oauth_callback_url' => 'crwdns12260:0crwdne12260:0',
|
||||
'oauth_personal_access_tokens' => 'crwdns14674:0crwdne14674:0',
|
||||
'oauth_personal_access_tokens_none' => 'crwdns14676:0crwdne14676:0',
|
||||
'oauth_client' => 'crwdns14678:0crwdne14678:0',
|
||||
'oauth_deleted_user' => 'crwdns14680:0crwdne14680:0',
|
||||
'oauth_token_status_revoked' => 'crwdns14682:0crwdne14682:0',
|
||||
'oauth_token_status_expired' => 'crwdns14684:0crwdne14684:0',
|
||||
'oauth_token_status_active' => 'crwdns14686:0crwdne14686:0',
|
||||
'oauth_revoke' => 'crwdns14688:0crwdne14688:0',
|
||||
'oauth_unrevoke' => 'crwdns14690:0crwdne14690:0',
|
||||
'create_client' => 'crwdns12262:0crwdne12262:0',
|
||||
'no_scopes' => 'crwdns12264:0crwdne12264:0',
|
||||
'asset_tag_title' => 'crwdns6409:0crwdne6409:0',
|
||||
@@ -346,6 +361,7 @@ return [
|
||||
'general_title' => 'crwdns6425:0crwdne6425:0',
|
||||
'mail_test' => 'crwdns6427:0crwdne6427:0',
|
||||
'mail_test_help' => 'crwdns6429:0crwdne6429:0',
|
||||
'mail_test_no_email' => 'crwdns14696:0crwdne14696:0',
|
||||
'filter_by_keyword' => 'crwdns6431:0crwdne6431:0',
|
||||
'security' => 'crwdns6433:0crwdne6433:0',
|
||||
'security_title' => 'crwdns6435:0crwdne6435:0',
|
||||
@@ -525,6 +541,7 @@ return [
|
||||
'purge' => 'crwdns12854:0crwdne12854:0',
|
||||
'security' => 'crwdns12856:0crwdne12856:0',
|
||||
'notifications' => 'crwdns13284:0crwdne13284:0',
|
||||
'oauth' => 'crwdns14692:0crwdne14692:0',
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
@@ -56,4 +56,21 @@ return [
|
||||
'not_saved' => 'crwdns13053:0crwdne13053:0',
|
||||
'mismatch' => 'crwdns13055:0crwdne13055:0',
|
||||
],
|
||||
'oauth' => [
|
||||
'token_revoked' => 'crwdns14624:0crwdne14624:0',
|
||||
'token_unrevoked' => 'crwdns14626:0crwdne14626:0',
|
||||
'token_not_found' => 'crwdns14628:0crwdne14628:0',
|
||||
'token_revoke_error' => 'crwdns14630:0crwdne14630:0',
|
||||
'token_unrevoke_error' => 'crwdns14632:0crwdne14632:0',
|
||||
'client_created' => 'crwdns14634:0crwdne14634:0',
|
||||
'client_updated' => 'crwdns14636:0crwdne14636:0',
|
||||
'client_deleted' => 'crwdns14638:0crwdne14638:0',
|
||||
'client_revoked' => 'crwdns14640:0crwdne14640:0',
|
||||
'client_unrevoked' => 'crwdns14642:0crwdne14642:0',
|
||||
'client_not_found' => 'crwdns14644:0crwdne14644:0',
|
||||
'token_deleted' => 'crwdns14646:0crwdne14646:0',
|
||||
'client_delete_denied' => 'crwdns14648:0crwdne14648:0',
|
||||
'client_edit_denied' => 'crwdns14650:0crwdne14650:0',
|
||||
'token_delete_denied' => 'crwdns14652:0crwdne14652:0',
|
||||
],
|
||||
];
|
||||
|
||||
@@ -14,6 +14,8 @@ return [
|
||||
'filetype_info' => 'crwdns1391:0crwdne1391:0',
|
||||
'history_user' => 'crwdns1129:0crwdne1129:0',
|
||||
'info' => 'crwdns1848:0crwdne1848:0',
|
||||
'send_acceptance_reminder' => 'crwdns14710:0crwdne14710:0',
|
||||
'unaccepted_items' => 'crwdns14712:0crwdne14712:0',
|
||||
'restore_user' => 'crwdns1912:0crwdne1912:0',
|
||||
'last_login' => 'crwdns1130:0crwdne1130:0',
|
||||
'ldap_config_text' => 'crwdns14248:0crwdne14248:0',
|
||||
|
||||
@@ -15,6 +15,7 @@ return [
|
||||
'user_deleted_warning' => 'crwdns1133:0crwdne1133:0',
|
||||
'ldap_not_configured' => 'crwdns1412:0crwdne1412:0',
|
||||
'password_resets_sent' => 'crwdns5922:0crwdne5922:0',
|
||||
'not_activated' => 'crwdns14716:0crwdne14716:0',
|
||||
'password_reset_sent' => 'crwdns6087:0crwdne6087:0',
|
||||
'user_has_no_email' => 'crwdns10536:0crwdne10536:0',
|
||||
'log_record_not_found' => 'crwdns11844:0crwdne11844:0',
|
||||
@@ -30,6 +31,7 @@ return [
|
||||
'unsuspend' => 'crwdns798:0crwdne798:0',
|
||||
'restored' => 'crwdns799:0crwdne799:0',
|
||||
'import' => 'crwdns1194:0crwdne1194:0',
|
||||
'acceptance_reminder_sent' => 'crwdns14718:0crwdne14718:0',
|
||||
],
|
||||
|
||||
'error' => [
|
||||
@@ -44,7 +46,7 @@ return [
|
||||
'delete_has_users_var' => 'crwdns12242:0crwdne12242:0',
|
||||
'unsuspend' => 'crwdns803:0crwdne803:0',
|
||||
'import' => 'crwdns1195:0crwdne1195:0',
|
||||
'asset_already_accepted' => 'crwdns1267:0crwdne1267:0',
|
||||
'asset_already_accepted' => 'crwdns14706:0crwdne14706:0',
|
||||
'accept_or_decline' => 'crwdns1346:0crwdne1346:0',
|
||||
'cannot_delete_yourself' => 'crwdns12244:0crwdne12244:0',
|
||||
'incorrect_user_accepted' => 'crwdns1483:0crwdne1483:0',
|
||||
@@ -54,6 +56,7 @@ return [
|
||||
'ldap_could_not_get_entries' => 'crwdns1416:0crwdne1416:0',
|
||||
'password_ldap' => 'crwdns1889:0crwdne1889:0',
|
||||
'multi_company_items_assigned' => 'crwdns12754:0crwdne12754:0',
|
||||
'no_pending_acceptances' => 'crwdns14720:0crwdne14720:0',
|
||||
],
|
||||
|
||||
'deletefile' => [
|
||||
|
||||
@@ -54,7 +54,7 @@ return [
|
||||
'avatar_upload' => 'crwdns1029:0crwdne1029:0',
|
||||
'back' => 'crwdns1030:0crwdne1030:0',
|
||||
'bad_data' => 'crwdns1334:0crwdne1334:0',
|
||||
'bulkaudit' => 'crwdns1915:0crwdne1915:0',
|
||||
'bulkaudit' => 'crwdns14726:0crwdne14726:0',
|
||||
'bulkaudit_status' => 'crwdns1916:0crwdne1916:0',
|
||||
'bulk_checkout' => 'crwdns1667:0crwdne1667:0',
|
||||
'bulk_edit' => 'crwdns6105:0crwdne6105:0',
|
||||
@@ -122,7 +122,7 @@ return [
|
||||
'debug_warning_text' => 'crwdns1828:0crwdne1828:0',
|
||||
'delete' => 'crwdns1046:0crwdne1046:0',
|
||||
'delete_confirm' => 'crwdns2020:0crwdne2020:0',
|
||||
'delete_confirm_no_undo' => 'crwdns14510:0crwdne14510:0',
|
||||
'delete_confirm_no_undo' => 'crwdns14568:0crwdne14568:0',
|
||||
'deleted' => 'crwdns1047:0crwdne1047:0',
|
||||
'delete_seats' => 'crwdns1430:0crwdne1430:0',
|
||||
'deletion_failed' => 'crwdns6117:0crwdne6117:0',
|
||||
@@ -154,7 +154,7 @@ return [
|
||||
'first_checkout' => 'crwdns14484:0crwdne14484:0',
|
||||
'generate' => 'crwdns1140:0crwdne1140:0',
|
||||
'generate_labels' => 'crwdns6125:0crwdne6125:0',
|
||||
'github_markdown' => 'crwdns1981:0crwdne1981:0',
|
||||
'github_markdown' => 'crwdns14622:0crwdne14622:0',
|
||||
'groups' => 'crwdns1054:0crwdne1054:0',
|
||||
'gravatar_email' => 'crwdns1117:0crwdne1117:0',
|
||||
'gravatar_url' => 'crwdns6127:0crwdne6127:0',
|
||||
@@ -167,7 +167,7 @@ return [
|
||||
'image_upload' => 'crwdns1058:0crwdne1058:0',
|
||||
'filetypes_accepted_help' => 'crwdns12622:0crwdne12622:0',
|
||||
'filetypes_size_help' => 'crwdns12624:0crwdne12624:0',
|
||||
'image_filetypes_help' => 'crwdns14512:0crwdne14512:0',
|
||||
'image_filetypes_help' => 'crwdns14570:0crwdne14570:0',
|
||||
'unaccepted_image_type' => 'crwdns11365:0crwdne11365:0',
|
||||
'import' => 'crwdns1411:0crwdne1411:0',
|
||||
'documentation' => 'crwdns14462:0crwdne14462:0',
|
||||
@@ -224,6 +224,9 @@ return [
|
||||
'next_audit_date_help' => 'crwdns12196:0crwdne12196:0',
|
||||
'audit_images_help' => 'crwdns12198:0crwdne12198:0',
|
||||
'no_email' => 'crwdns12130:0crwdne12130:0',
|
||||
'no_value' => 'crwdns14574:0crwdne14574:0',
|
||||
'device_eol' => 'crwdns14576:0crwdne14576:0',
|
||||
'na' => 'crwdns14578:0crwdne14578:0',
|
||||
'last_audit' => 'crwdns1920:0crwdne1920:0',
|
||||
'new' => 'crwdns1668:0crwdne1668:0',
|
||||
'no_depreciation' => 'crwdns1073:0crwdne1073:0',
|
||||
@@ -271,7 +274,7 @@ return [
|
||||
'rtd' => 'crwdns14338:0crwdne14338:0',
|
||||
'requested_date' => 'crwdns6149:0crwdne6149:0',
|
||||
'requested_assets' => 'crwdns6151:0crwdne6151:0',
|
||||
'requested_assets_menu' => 'crwdns14524:0crwdne14524:0',
|
||||
'requested_assets_menu' => 'crwdns14572:0crwdne14572:0',
|
||||
'request_canceled' => 'crwdns1703:0crwdne1703:0',
|
||||
'request_item' => 'crwdns12204:0crwdne12204:0',
|
||||
'external_link_tooltip' => 'crwdns12206:0crwdne12206:0',
|
||||
@@ -558,6 +561,11 @@ return [
|
||||
'error_user_company_accept_view' => 'crwdns11787:0crwdne11787:0',
|
||||
'error_assets_already_checked_out' => 'crwdns13826:0crwdne13826:0',
|
||||
'assigned_assets_removed' => 'crwdns13830:0crwdne13830:0',
|
||||
'upload_files' => 'crwdns14580:0crwdne14580:0',
|
||||
'uploaded_files' => 'crwdns14582:0crwdne14582:0',
|
||||
'sign_in_place' => 'crwdns14700:0crwdne14700:0',
|
||||
'sign_in_place_help' => 'crwdns14702:0crwdne14702:0',
|
||||
'unauthorized' => 'crwdns14714:0crwdne14714:0',
|
||||
'importer' => [
|
||||
'checked_out_to_fullname' => 'crwdns11639:0crwdne11639:0',
|
||||
'checked_out_to_first_name' => 'crwdns11641:0crwdne11641:0',
|
||||
@@ -661,12 +669,16 @@ return [
|
||||
'child_locations' => 'crwdns13796:0crwdne13796:0',
|
||||
'append' => 'crwdns14416:0crwdne14416:0',
|
||||
'optional' => 'crwdns14448:0crwdne14448:0',
|
||||
'audit_by_field' => 'crwdns14728:0crwdne14728:0',
|
||||
'audit_by_field_help' => 'crwdns14730:0crwdne14730:0',
|
||||
'audit_key' => 'crwdns14732:0crwdne14732:0',
|
||||
|
||||
// Add form placeholders here
|
||||
'placeholders' => [
|
||||
'notes' => 'crwdns12878:0crwdne12878:0',
|
||||
],
|
||||
|
||||
'last_note' => 'crwdns14584:0crwdne14584:0',
|
||||
'bulk_delete_associations' => [
|
||||
'general_assoc_warning' => 'crwdns13850:0crwdne13850:0',
|
||||
'assoc_assets' => 'crwdns13852:0crwdne13852:0',
|
||||
@@ -690,26 +702,6 @@ return [
|
||||
'checkin_item' => 'crwdns12918:0crwdne12918:0',
|
||||
],
|
||||
|
||||
'skins' => [
|
||||
'site_default' => 'crwdns13057:0crwdne13057:0',
|
||||
'default_blue' => 'crwdns13059:0crwdne13059:0',
|
||||
'blue_dark' => 'crwdns13061:0crwdne13061:0',
|
||||
'green' => 'crwdns13758:0crwdne13758:0',
|
||||
'green_dark' => 'crwdns13065:0crwdne13065:0',
|
||||
'red' => 'crwdns13760:0crwdne13760:0',
|
||||
'red_dark' => 'crwdns13069:0crwdne13069:0',
|
||||
'orange' => 'crwdns13762:0crwdne13762:0',
|
||||
'orange_dark' => 'crwdns13073:0crwdne13073:0',
|
||||
'black' => 'crwdns13075:0crwdne13075:0',
|
||||
'black_dark' => 'crwdns13077:0crwdne13077:0',
|
||||
'purple' => 'crwdns13079:0crwdne13079:0',
|
||||
'purple_dark' => 'crwdns13081:0crwdne13081:0',
|
||||
'yellow' => 'crwdns13083:0crwdne13083:0',
|
||||
'yellow_dark' => 'crwdns13085:0crwdne13085:0',
|
||||
'high_contrast' => 'crwdns13087:0crwdne13087:0',
|
||||
|
||||
],
|
||||
|
||||
'select_all_none' => 'crwdns12927:0crwdne12927:0',
|
||||
'generic_model_not_found' => 'crwdns12920:0crwdne12920:0',
|
||||
'report_not_editable' => 'crwdns14550:0crwdne14550:0',
|
||||
@@ -753,4 +745,7 @@ return [
|
||||
|
||||
'months_plural' => 'crwdns13470:0crwdne13470:0',
|
||||
|
||||
'token_unrevoked' => 'crwdns14654:0crwdne14654:0',
|
||||
'token_revoked' => 'crwdns14656:0crwdne14656:0',
|
||||
|
||||
];
|
||||
|
||||
@@ -90,7 +90,7 @@ return [
|
||||
'password' => 'crwdns12728:0crwdne12728:0',
|
||||
'password_reset' => 'crwdns1750:0crwdne1750:0',
|
||||
'read_the_terms' => 'crwdns1751:0crwdne1751:0',
|
||||
'read_the_terms_and_click' => 'crwdns12072:0crwdne12072:0',
|
||||
'read_the_terms_and_click' => 'crwdns14694:0crwdne14694:0',
|
||||
'click_here_to_review_terms_and_accept_item' => 'crwdns14534:0crwdne14534:0',
|
||||
'requested' => 'crwdns12730:0crwdne12730:0',
|
||||
'reset_link' => 'crwdns1754:0crwdne1754:0',
|
||||
|
||||
@@ -107,8 +107,49 @@ return [
|
||||
],
|
||||
'accessoriesfiles' => [
|
||||
'name' => 'crwdns13980:0crwdne13980:0',
|
||||
'note' => 'crwdns13982:0crwdne13982:0',
|
||||
'note' => 'crwdns14590:0crwdne14590:0',
|
||||
],
|
||||
|
||||
'assetsfiles' => [
|
||||
'name' => 'crwdns14592:0crwdne14592:0',
|
||||
'note' => 'crwdns14594:0crwdne14594:0',
|
||||
],
|
||||
|
||||
'usersfiles' => [
|
||||
'name' => 'crwdns14596:0crwdne14596:0',
|
||||
'note' => 'crwdns14598:0crwdne14598:0',
|
||||
],
|
||||
|
||||
'modelsfiles' => [
|
||||
'name' => 'crwdns14600:0crwdne14600:0',
|
||||
'note' => 'crwdns14602:0crwdne14602:0',
|
||||
],
|
||||
|
||||
'departmentsfiles' => [
|
||||
'name' => 'crwdns14604:0crwdne14604:0',
|
||||
'note' => 'crwdns14606:0crwdne14606:0',
|
||||
],
|
||||
|
||||
'suppliersfiles' => [
|
||||
'name' => 'crwdns14608:0crwdne14608:0',
|
||||
'note' => 'crwdns14610:0crwdne14610:0',
|
||||
],
|
||||
|
||||
'locationsfiles' => [
|
||||
'name' => 'crwdns14612:0crwdne14612:0',
|
||||
'note' => 'crwdns14614:0crwdne14614:0',
|
||||
],
|
||||
|
||||
'companiesfiles' => [
|
||||
'name' => 'crwdns14616:0crwdne14616:0',
|
||||
'note' => 'crwdns14618:0crwdne14618:0',
|
||||
],
|
||||
|
||||
'consumablesfiles' => [
|
||||
'name' => 'crwdns14000:0crwdne14000:0',
|
||||
'note' => 'crwdns14620:0crwdne14620:0',
|
||||
],
|
||||
|
||||
'consumables' => [
|
||||
'name' => 'crwdns13984:0crwdne13984:0',
|
||||
'note' => 'crwdns13986:0crwdne13986:0',
|
||||
@@ -129,10 +170,7 @@ return [
|
||||
'name' => 'crwdns13996:0crwdne13996:0',
|
||||
'note' => 'crwdns13998:0crwdne13998:0',
|
||||
],
|
||||
'consumablesfiles' => [
|
||||
'name' => 'crwdns14000:0crwdne14000:0',
|
||||
'note' => 'crwdns14002:0crwdne14002:0',
|
||||
],
|
||||
|
||||
'licenses' => [
|
||||
'name' => 'crwdns14004:0crwdne14004:0',
|
||||
'note' => 'crwdns14006:0crwdne14006:0',
|
||||
@@ -161,6 +199,11 @@ return [
|
||||
'name' => 'crwdns14024:0crwdne14024:0',
|
||||
'note' => 'crwdns14026:0crwdne14026:0',
|
||||
],
|
||||
'componentsfiles' => [
|
||||
'name' => 'crwdns14044:0crwdne14044:0',
|
||||
'note' => 'crwdns14046:0crwdne14046:0',
|
||||
],
|
||||
|
||||
'licenseskeys' => [
|
||||
'name' => 'crwdns14028:0crwdne14028:0',
|
||||
'note' => 'crwdns14030:0crwdne14030:0',
|
||||
@@ -181,10 +224,7 @@ return [
|
||||
'componentsdelete' => [
|
||||
'name' => 'crwdns14042:0crwdne14042:0',
|
||||
],
|
||||
'componentsfiles' => [
|
||||
'name' => 'crwdns14044:0crwdne14044:0',
|
||||
'note' => 'crwdns14046:0crwdne14046:0',
|
||||
],
|
||||
|
||||
'componentscheckout' => [
|
||||
'name' => 'crwdns14048:0crwdne14048:0',
|
||||
'note' => 'crwdns14050:0crwdne14050:0',
|
||||
|
||||
@@ -9,7 +9,7 @@ return [
|
||||
'edit' => 'Wysig bykomstighede',
|
||||
'eula_text' => 'Kategorie EULA',
|
||||
'eula_text_help' => 'Hierdie veld laat u toe om u EULA\'s vir spesifieke soorte bates aan te pas. As u slegs een EULA vir al u bates het, kan u die onderstaande boks selekteer om die primêre standaard te gebruik.',
|
||||
'require_acceptance' => 'Vereis gebruikers om die aanvaarding van bates in hierdie kategorie te bevestig.',
|
||||
'require_acceptance' => 'Require users to confirm acceptance of item in this category.',
|
||||
'no_default_eula' => 'Geen primêre standaard EULA gevind nie. Voeg een by Instellings.',
|
||||
'total' => 'totale',
|
||||
'remaining' => 'opgelewer',
|
||||
|
||||
@@ -17,6 +17,7 @@ return [
|
||||
'name' => 'Kategorie Naam',
|
||||
'require_acceptance' => 'Vereis gebruikers om die aanvaarding van bates in hierdie kategorie te bevestig.',
|
||||
'required_acceptance' => 'Hierdie gebruiker sal per e-pos met \'n skakel gestuur word om die aanvaarding van hierdie item te bevestig.',
|
||||
'global_signature_required_notice' => 'User signatures are currently required globally via the admin settings, so signatures will still be required regardless of this category setting if the item is checked out to a user (versus a location, etc).',
|
||||
'required_eula' => 'Hierdie gebruiker sal \'n afskrif van die EULA ontvang',
|
||||
'no_default_eula' => 'Geen primêre standaard EULA gevind nie. Voeg een by Instellings.',
|
||||
'update' => 'Opdateer kategorie',
|
||||
|
||||
@@ -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.',
|
||||
|
||||
@@ -7,5 +7,6 @@ return [
|
||||
'invalid_return_value' => 'Invalid value returned from :name. Expected :expected, got :actual.',
|
||||
|
||||
'does_not_exist' => 'Label does not exist',
|
||||
|
||||
'use_new_label_engine_for_api' => 'Enable the New Label Engine to load labels via the API',
|
||||
'label_not_created' => 'Label object could not be created',
|
||||
];
|
||||
|
||||
@@ -8,7 +8,6 @@ return [
|
||||
'assoc_child_loc' => 'Hierdie ligging is tans die ouer van ten minste een kind se plek en kan nie uitgevee word nie. Werk asseblief jou liggings by om nie meer hierdie ligging te verwys nie en probeer weer.',
|
||||
'assigned_assets' => 'Assigned Assets',
|
||||
'current_location' => 'Current Location',
|
||||
'open_map' => 'Open in :map_provider_icon Maps',
|
||||
'deleted_warning' => 'This location has been deleted. Please restore it before attempting to make any changes.',
|
||||
|
||||
'create' => [
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
return [
|
||||
'select_type' => 'Select Maintenance Type',
|
||||
'asset_maintenance_type' => 'Asset Maintenance Type',
|
||||
'asset_maintenance_type' => 'tipe',
|
||||
'title' => 'Titel',
|
||||
'start_date' => 'Start Date',
|
||||
'completion_date' => 'Completion Date',
|
||||
'cost' => 'koste',
|
||||
'is_warranty' => 'Garantieverbetering',
|
||||
'asset_maintenance_time' => 'Asset Maintenance Time (in days)',
|
||||
'asset_maintenance_time' => 'Duration',
|
||||
'notes' => 'notas',
|
||||
'update' => 'Update Asset Maintenance',
|
||||
'create' => 'Create Asset Maintenance',
|
||||
|
||||
@@ -309,7 +309,7 @@ return [
|
||||
'two_factor_enabled_edit_not_allowed' => 'Jou administrateur laat jou nie toe om hierdie instelling te wysig nie.',
|
||||
'two_factor_enrollment_text' => 'Twee faktor verifikasie is nodig, maar jou toestel is nog nie ingeskryf nie. Maak jou Google Authenticator-program oop en scan die QR-kode hieronder om jou toestel in te skryf. Sodra jy jou toestel ingeskryf het, voer die kode hieronder in',
|
||||
'require_accept_signature' => 'Vereis Handtekening',
|
||||
'require_accept_signature_help_text' => 'As u hierdie kenmerk aanskakel, sal gebruikers fisies moet afmeld wanneer hulle \'n bate aanvaar.',
|
||||
'require_accept_signature_help_text' => 'Enabling this feature will require users to physically sign off on accepting items. This will override any category-specific signature requirements.',
|
||||
'require_checkinout_notes' => 'Require Notes on Checkin/Checkout',
|
||||
'require_checkinout_notes_help_text' => 'Enabling this feature will require the note fields to be populated when checking in or checking out an asset.',
|
||||
'left' => 'links',
|
||||
@@ -324,15 +324,30 @@ return [
|
||||
'username_format_help' => 'This setting will only be used by the import process if a username is not provided and we have to generate a username for you.',
|
||||
'oauth_title' => 'OAuth API Settings',
|
||||
'oauth_clients' => 'OAuth Clients',
|
||||
'oauth' => 'OAuth',
|
||||
'oauth_help' => 'Oauth Endpoint Settings',
|
||||
'oauth' => 'OAuth & API',
|
||||
'oauth_help' => 'Oauth Endpoint Settings and API tokens',
|
||||
'oauth_no_clients' => 'You have not created any OAuth clients yet.',
|
||||
'oauth_no_applications' => 'You have not created any Authorized Applications yet.',
|
||||
'oauth_secret' => 'Secret',
|
||||
'oauth_authorized_apps' => 'Authorized Applications',
|
||||
'oauth_redirect_url' => 'Redirect URL',
|
||||
'oauth_name_help' => ' Something your users will recognize and trust.',
|
||||
'oauth_scopes' => 'Scopes',
|
||||
'oauth_client_type' => 'Client Type',
|
||||
'oauth_client_type_oauth' => 'OAuth Client',
|
||||
'oauth_client_type_personal_access' => 'Personal Access Client',
|
||||
'oauth_client_type_password_grant' => 'Password Grant Client',
|
||||
'oauth_associated_token_count' => 'Token Count',
|
||||
'oauth_callback_url' => 'Your application authorization callback URL.',
|
||||
'oauth_personal_access_tokens' => 'User API Tokens (Personal Access Tokens)',
|
||||
'oauth_personal_access_tokens_none' => 'No personal access tokens found.',
|
||||
'oauth_client' => 'Client',
|
||||
'oauth_deleted_user' => 'Deleted user (ID: :id)',
|
||||
'oauth_token_status_revoked' => 'Revoked',
|
||||
'oauth_token_status_expired' => 'Expired',
|
||||
'oauth_token_status_active' => 'aktiewe',
|
||||
'oauth_revoke' => 'Revoke',
|
||||
'oauth_unrevoke' => 'Unrevoke',
|
||||
'create_client' => 'Create Client',
|
||||
'no_scopes' => 'No scopes',
|
||||
'asset_tag_title' => 'Update Asset Tag Settings',
|
||||
@@ -346,6 +361,7 @@ return [
|
||||
'general_title' => 'Update General Settings',
|
||||
'mail_test' => 'Send Test',
|
||||
'mail_test_help' => 'This will attempt to send a test mail to :replyto.',
|
||||
'mail_test_no_email' => 'MAIL_REPLYTO_ADDR not set or has no value .env config file. Cannot send test email. Please update this value in your configuration file with a valid email address.',
|
||||
'filter_by_keyword' => 'Filter by setting keyword',
|
||||
'security' => 'Security',
|
||||
'security_title' => 'Update Security Settings',
|
||||
@@ -525,6 +541,7 @@ return [
|
||||
'purge' => 'permanently delete',
|
||||
'security' => 'password, passwords, requirements, two factor, two-factor, common passwords, remote login, logout, authentication',
|
||||
'notifications' => 'alerts, email, notifications, audit, threshold, email alerts, cc',
|
||||
'oauth' => 'oauth, oath, api, personal access keys, tokens',
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
@@ -56,4 +56,21 @@ return [
|
||||
'not_saved' => 'Your settings were not saved.',
|
||||
'mismatch' => 'There is 1 item in the database that need your attention before you can enable location scoping.|There are :count items in the database that need your attention before you can enable location scoping.',
|
||||
],
|
||||
'oauth' => [
|
||||
'token_revoked' => 'Personal access token revoked successfully.',
|
||||
'token_unrevoked' => 'Personal access token reinstated successfully.',
|
||||
'token_not_found' => 'That personal access token could not be found.',
|
||||
'token_revoke_error' => 'An error occurred while revoking the token.',
|
||||
'token_unrevoke_error' => 'An error occurred while reinstating the token.',
|
||||
'client_created' => 'OAuth client created successfully.',
|
||||
'client_updated' => 'OAuth client updated successfully.',
|
||||
'client_deleted' => 'OAuth client deleted successfully.',
|
||||
'client_revoked' => 'OAuth client revoked successfully.',
|
||||
'client_unrevoked' => 'OAuth client reinstated successfully.',
|
||||
'client_not_found' => 'That OAuth client could not be found.',
|
||||
'token_deleted' => 'Token revoked successfully.',
|
||||
'client_delete_denied' => 'You are not authorized to delete this client.',
|
||||
'client_edit_denied' => 'You are not authorized to edit this client.',
|
||||
'token_delete_denied' => 'You are not authorized to revoke this token.',
|
||||
],
|
||||
];
|
||||
|
||||
@@ -14,6 +14,8 @@ return [
|
||||
'filetype_info' => 'Toegelate filetipes is png, gif, jpg, jpeg, doc, docx, pdf, txt, zip en rar.',
|
||||
'history_user' => 'Geskiedenis vir: naam',
|
||||
'info' => 'info',
|
||||
'send_acceptance_reminder' => 'Send Reminder',
|
||||
'unaccepted_items' => ':count Unaccepted Items',
|
||||
'restore_user' => 'Klik hier om dit te herstel.',
|
||||
'last_login' => 'Laaste Aanmelding',
|
||||
'ldap_config_text' => 'The selected location will be set for ALL imported users. This will overwrite their existing location, and is an unusual use-case, so leaving this blank is typically best.',
|
||||
|
||||
@@ -15,6 +15,7 @@ return [
|
||||
'user_deleted_warning' => 'Hierdie gebruiker is verwyder. Jy sal hierdie gebruiker moet herstel om hulle te wysig of nuwe bates toe te ken.',
|
||||
'ldap_not_configured' => 'LDAP-integrasie is nie vir hierdie installasie gekonfigureer nie.',
|
||||
'password_resets_sent' => 'The selected users who are activated and have a valid email addresses have been sent a password reset link.',
|
||||
'not_activated' => 'This user cannot login, so they cannot accept assets via email.',
|
||||
'password_reset_sent' => 'A password reset link has been sent to :email!',
|
||||
'user_has_no_email' => 'This user does not have an email address in their profile.',
|
||||
'log_record_not_found' => 'A matching log record for this user could not be found.',
|
||||
@@ -30,6 +31,7 @@ return [
|
||||
'unsuspend' => 'Gebruiker is suksesvol ingetrek.',
|
||||
'restored' => 'Gebruiker is suksesvol herstel.',
|
||||
'import' => 'Gebruikers suksesvol ingevoer.',
|
||||
'acceptance_reminder_sent' => 'Acceptance reminder sent for :count pending item.|Acceptance reminder sent for :count pending items.',
|
||||
],
|
||||
|
||||
'error' => [
|
||||
@@ -44,7 +46,7 @@ return [
|
||||
'delete_has_users_var' => 'This user still manages another user. Please select another manager for that user first.|This user still manages :count users. Please select another manager for them first.',
|
||||
'unsuspend' => 'Daar was \'n probleem wat die gebruiker onttrek het. Probeer asseblief weer.',
|
||||
'import' => 'Kon nie gebruikers invoer nie. Probeer asseblief weer.',
|
||||
'asset_already_accepted' => 'Hierdie bate is reeds aanvaar.',
|
||||
'asset_already_accepted' => 'This item has already been accepted.',
|
||||
'accept_or_decline' => 'U moet hierdie bate aanvaar of afkeur.',
|
||||
'cannot_delete_yourself' => 'We would feel really bad if you deleted yourself, please reconsider.',
|
||||
'incorrect_user_accepted' => 'Die bate wat u probeer aanvaar het, is nie na u gekontroleer nie.',
|
||||
@@ -54,6 +56,7 @@ return [
|
||||
'ldap_could_not_get_entries' => 'Kon nie inskrywings van die LDAP-bediener kry nie. Gaan asseblief die LDAP-bediener opstelling in die LDAP-konfigurasie lêer. <br>Error van LDAP-bediener:',
|
||||
'password_ldap' => 'Die wagwoord vir hierdie rekening word bestuur deur LDAP / Active Directory. Kontak asseblief u IT-afdeling om u wagwoord te verander.',
|
||||
'multi_company_items_assigned' => 'This user has items assigned that belong to a different company. Please check them in or edit their company.',
|
||||
'no_pending_acceptances' => 'This user has no pending acceptances to remind them about.',
|
||||
],
|
||||
|
||||
'deletefile' => [
|
||||
|
||||
@@ -54,7 +54,7 @@ return [
|
||||
'avatar_upload' => 'Laai avatar op',
|
||||
'back' => 'terug',
|
||||
'bad_data' => 'Niks gevind. Miskien slegte data?',
|
||||
'bulkaudit' => 'Grootmaat Oudit',
|
||||
'bulkaudit' => 'Scanner Bulk Audit',
|
||||
'bulkaudit_status' => 'Ouditstatus',
|
||||
'bulk_checkout' => 'Grootmaat Checkout',
|
||||
'bulk_edit' => 'Bulk Edit',
|
||||
@@ -122,7 +122,7 @@ return [
|
||||
'debug_warning_text' => 'Hierdie program word uitgevoer in die produksiemodus met debugging aangeskakel. Dit kan sensitiewe data blootstel indien u aansoek vir die buitewêreld toeganklik is. Deaktiveer debug-modus deur die <code>APP_DEBUG</code>-waarde in jou <code>.env</code>-lêer te stel na <code>false</code>.',
|
||||
'delete' => 'verwyder',
|
||||
'delete_confirm' => 'Are you sure you wish to delete :item?',
|
||||
'delete_confirm_no_undo' => 'Are you sure you wish to delete :item? This cannot be undone.',
|
||||
'delete_confirm_no_undo' => 'Are you sure, you wish to delete :item? This cannot be undone.',
|
||||
'deleted' => 'geskrap',
|
||||
'delete_seats' => 'Plekke verwyder',
|
||||
'deletion_failed' => 'Deletion failed',
|
||||
@@ -154,7 +154,7 @@ return [
|
||||
'first_checkout' => '1<sup>st</sup> Checkout',
|
||||
'generate' => 'genereer',
|
||||
'generate_labels' => 'Generate Labels',
|
||||
'github_markdown' => 'This field accepts <a href="https://help.github.com/articles/github-flavored-markdown/">Github flavored markdown</a>.',
|
||||
'github_markdown' => 'This field accepts <a href="https://help.github.com/articles/github-flavored-markdown/" target="_blank">Github flavored markdown</a>.',
|
||||
'groups' => 'groepe',
|
||||
'gravatar_email' => 'Gravatar e-pos adres',
|
||||
'gravatar_url' => '<a href="http://gravatar.com"><small>Change your avatar at Gravatar.com</small></a>.',
|
||||
@@ -167,7 +167,7 @@ return [
|
||||
'image_upload' => 'Laai prent op',
|
||||
'filetypes_accepted_help' => 'Accepted filetype is :types. The maximum size allowed is :size.|Accepted filetypes are :types. The maximum upload size allowed is :size.',
|
||||
'filetypes_size_help' => 'The maximum upload size allowed is :size.',
|
||||
'image_filetypes_help' => 'Accepted filetypes are jpg, webp, png, gif, svg, and avif. The maximum upload size allowed is :size.',
|
||||
'image_filetypes_help' => 'Accepted Filetypes are jpg, webp, png, gif, svg, and avif. The maximum upload size allowed is :size.',
|
||||
'unaccepted_image_type' => 'This image file was not readable. Accepted filetypes are jpg, webp, png, gif, and svg. The mimetype of this file is: :mimetype.',
|
||||
'import' => 'invoer',
|
||||
'documentation' => 'Open documentation in a new link',
|
||||
@@ -224,6 +224,9 @@ return [
|
||||
'next_audit_date_help' => 'If you use auditing in your organization, this is usually automatically calculated based on the asset's last audit date and audit frequency (in <code>Admin Settings > Alerts</code>) and you can leave this blank. You can manually set this date here if you need to, but it must be later than the last audit date. ',
|
||||
'audit_images_help' => 'You can find audit images in the asset\'s history tab.',
|
||||
'no_email' => 'No email address associated with this user',
|
||||
'no_value' => 'No value',
|
||||
'device_eol' => 'Device EOL',
|
||||
'na' => 'N/A',
|
||||
'last_audit' => 'Laaste Oudit',
|
||||
'new' => 'nuwe!',
|
||||
'no_depreciation' => 'Geen Waardevermindering',
|
||||
@@ -271,7 +274,7 @@ return [
|
||||
'rtd' => 'Klaar om te implementeer',
|
||||
'requested_date' => 'Requested Date',
|
||||
'requested_assets' => 'Requested Assets',
|
||||
'requested_assets_menu' => 'Requested Items',
|
||||
'requested_assets_menu' => 'Requestable Items',
|
||||
'request_canceled' => 'Versoek gekanselleer',
|
||||
'request_item' => 'Request this item',
|
||||
'external_link_tooltip' => 'External link to',
|
||||
@@ -559,6 +562,11 @@ return [
|
||||
'error_user_company_accept_view' => 'An Asset assigned to you belongs to a different company so you can\'t accept nor deny it, please check with your manager',
|
||||
'error_assets_already_checked_out' => 'One or more of the assets are already checked out',
|
||||
'assigned_assets_removed' => 'The following were removed from the selected assets because they are already checked out',
|
||||
'upload_files' => 'Upload Files',
|
||||
'uploaded_files' => 'Uploaded Files',
|
||||
'sign_in_place' => 'Sign/Accept in place',
|
||||
'sign_in_place_help' => 'Check this box if you have the user present and wish for them to accept the item and sign/accept the EULA (when applicable) right now.',
|
||||
'unauthorized' => 'Unauthorized or unauthenticated.',
|
||||
'importer' => [
|
||||
'checked_out_to_fullname' => 'Checked Out to: Full Name',
|
||||
'checked_out_to_first_name' => 'Checked Out to: First Name',
|
||||
@@ -662,12 +670,16 @@ return [
|
||||
'child_locations' => 'Child Locations',
|
||||
'append' => 'Append',
|
||||
'optional' => 'OPTIONAL',
|
||||
'audit_by_field' => 'Audit by Field',
|
||||
'audit_by_field_help' => 'Auditing by scanning serial numbers is only an available option if serial numbers are required to be unique in the Admin Settings.',
|
||||
'audit_key' => 'bate',
|
||||
|
||||
// Add form placeholders here
|
||||
'placeholders' => [
|
||||
'notes' => 'Add a note',
|
||||
],
|
||||
|
||||
'last_note' => 'Last Note',
|
||||
'bulk_delete_associations' => [
|
||||
'general_assoc_warning' => ':item_name still has associated items. Please remove them before deleting this :item.',
|
||||
'assoc_assets' => ':item_name is currently associated with :asset_count asset(s) and cannot be deleted. Please update your assets to no longer reference this :item and try again.',
|
||||
@@ -691,26 +703,6 @@ return [
|
||||
'checkin_item' => 'Checkin :name',
|
||||
],
|
||||
|
||||
'skins' => [
|
||||
'site_default' => 'Site Default',
|
||||
'default_blue' => 'Default Blue',
|
||||
'blue_dark' => 'Blue (Dark Mode)',
|
||||
'green' => 'Green',
|
||||
'green_dark' => 'Green (Dark Mode)',
|
||||
'red' => 'Red',
|
||||
'red_dark' => 'Red (Dark Mode)',
|
||||
'orange' => 'Orange',
|
||||
'orange_dark' => 'Orange (Dark Mode)',
|
||||
'black' => 'Black',
|
||||
'black_dark' => 'Black (Dark Mode)',
|
||||
'purple' => 'Purple',
|
||||
'purple_dark' => 'Purple (Dark Mode)',
|
||||
'yellow' => 'Yellow',
|
||||
'yellow_dark' => 'Yellow (Dark Mode)',
|
||||
'high_contrast' => 'High Contrast',
|
||||
|
||||
],
|
||||
|
||||
'select_all_none' => 'Select/Unselect All',
|
||||
'generic_model_not_found' => 'That :model was not found or you do not have permission to access it',
|
||||
'report_not_editable' => 'You do not have permission to edit this report template',
|
||||
@@ -754,4 +746,7 @@ return [
|
||||
|
||||
'months_plural' => '1 month|:count months',
|
||||
|
||||
'token_unrevoked' => 'API token reinstated',
|
||||
'token_revoked' => 'API token revoked',
|
||||
|
||||
];
|
||||
|
||||
@@ -90,7 +90,7 @@ return [
|
||||
'password' => 'wagwoord',
|
||||
'password_reset' => 'Wagwoord Herstel',
|
||||
'read_the_terms' => 'Lees asseblief die gebruiksvoorwaardes hieronder.',
|
||||
'read_the_terms_and_click' => 'Please read the terms of use below, and click on the link at the bottom to confirm that you read and agree to the terms of use, and have received the asset.',
|
||||
'read_the_terms_and_click' => 'Please read the terms of use below, and click on the link at the bottom to confirm that you read and agree to the terms of use, and have received the item.',
|
||||
'click_here_to_review_terms_and_accept_item' => 'Click here to review the terms of use and accept the item|Click here to review the terms of use and accept the items',
|
||||
'requested' => 'versoek',
|
||||
'reset_link' => 'Jou wagwoord herstel skakel',
|
||||
|
||||
@@ -107,8 +107,49 @@ return [
|
||||
],
|
||||
'accessoriesfiles' => [
|
||||
'name' => 'Manage Accessory Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with accessories.',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with accessories. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'assetsfiles' => [
|
||||
'name' => 'Manage Asset Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with assets. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'usersfiles' => [
|
||||
'name' => 'Manage User Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with users. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'modelsfiles' => [
|
||||
'name' => 'Manage Model Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with asset models on both the model view and the asset view screens. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'departmentsfiles' => [
|
||||
'name' => 'Manage Department Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with departments. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'suppliersfiles' => [
|
||||
'name' => 'Manage Supplier Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with suppliers. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'locationsfiles' => [
|
||||
'name' => 'Manage Location Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with locations.(This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'companiesfiles' => [
|
||||
'name' => 'Manage Company Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with companies. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'consumablesfiles' => [
|
||||
'name' => 'Manage Consumable Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with consumables. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'consumables' => [
|
||||
'name' => 'Consumables',
|
||||
'note' => 'Grants access to the Consumables section of the application.',
|
||||
@@ -129,10 +170,7 @@ return [
|
||||
'name' => 'Check Out Consumables',
|
||||
'note' => 'Assign consumables in inventory by checking them out.',
|
||||
],
|
||||
'consumablesfiles' => [
|
||||
'name' => 'Manage Consumable Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with consumables.',
|
||||
],
|
||||
|
||||
'licenses' => [
|
||||
'name' => 'lisensies',
|
||||
'note' => 'Grants access to the Licenses section of the application.',
|
||||
@@ -161,6 +199,11 @@ return [
|
||||
'name' => 'Manage License Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with licenses.',
|
||||
],
|
||||
'componentsfiles' => [
|
||||
'name' => 'Manage Component Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with components.',
|
||||
],
|
||||
|
||||
'licenseskeys' => [
|
||||
'name' => 'Manage License Keys',
|
||||
'note' => 'Allows the user to view product keys associated with licenses.',
|
||||
@@ -181,10 +224,7 @@ return [
|
||||
'componentsdelete' => [
|
||||
'name' => 'Delete Components',
|
||||
],
|
||||
'componentsfiles' => [
|
||||
'name' => 'Manage Component Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with components.',
|
||||
],
|
||||
|
||||
'componentscheckout' => [
|
||||
'name' => 'Check Out Components',
|
||||
'note' => 'Assign components in inventory by checking them out.',
|
||||
|
||||
@@ -9,7 +9,7 @@ return [
|
||||
'edit' => 'Edit Accessory',
|
||||
'eula_text' => 'Category EULA',
|
||||
'eula_text_help' => 'This field allows you to customize your EULAs for specific types of assets. If you only have one EULA for all of your assets, you can check the box below to use the primary default.',
|
||||
'require_acceptance' => 'Require users to confirm acceptance of assets in this category.',
|
||||
'require_acceptance' => 'Require users to confirm acceptance of item in this category.',
|
||||
'no_default_eula' => 'No primary default EULA found. Add one in Settings.',
|
||||
'total' => 'Total',
|
||||
'remaining' => 'Avail',
|
||||
|
||||
@@ -17,6 +17,7 @@ return [
|
||||
'name' => 'Category Name',
|
||||
'require_acceptance' => 'Require users to confirm acceptance of assets in this category.',
|
||||
'required_acceptance' => 'This user will be emailed with a link to confirm acceptance of this item.',
|
||||
'global_signature_required_notice' => 'User signatures are currently required globally via the admin settings, so signatures will still be required regardless of this category setting if the item is checked out to a user (versus a location, etc).',
|
||||
'required_eula' => 'This user will be emailed a copy of the EULA',
|
||||
'no_default_eula' => 'No primary default EULA found. Add one in Settings.',
|
||||
'update' => 'Update Category',
|
||||
|
||||
@@ -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.',
|
||||
|
||||
@@ -7,5 +7,6 @@ return [
|
||||
'invalid_return_value' => 'Invalid value returned from :name. Expected :expected, got :actual.',
|
||||
|
||||
'does_not_exist' => 'Label does not exist',
|
||||
|
||||
'use_new_label_engine_for_api' => 'Enable the New Label Engine to load labels via the API',
|
||||
'label_not_created' => 'Label object could not be created',
|
||||
];
|
||||
|
||||
@@ -8,7 +8,6 @@ return [
|
||||
'assoc_child_loc' => 'This location is currently the parent of at least one child location and cannot be deleted. Please update your locations to no longer reference this location and try again. ',
|
||||
'assigned_assets' => 'Assigned Assets',
|
||||
'current_location' => 'Current Location',
|
||||
'open_map' => 'Open in :map_provider_icon Maps',
|
||||
'deleted_warning' => 'This location has been deleted. Please restore it before attempting to make any changes.',
|
||||
|
||||
'create' => [
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
return [
|
||||
'select_type' => 'Select Maintenance Type',
|
||||
'asset_maintenance_type' => 'የንብረት ጥገና አይነት',
|
||||
'asset_maintenance_type' => 'Type',
|
||||
'title' => 'መጠርያ',
|
||||
'start_date' => 'Start Date',
|
||||
'completion_date' => 'Completion Date',
|
||||
'cost' => 'Cost',
|
||||
'is_warranty' => 'Warranty Improvement',
|
||||
'asset_maintenance_time' => 'Asset Maintenance Time (in days)',
|
||||
'asset_maintenance_time' => 'Duration',
|
||||
'notes' => 'Notes',
|
||||
'update' => 'Update Asset Maintenance',
|
||||
'create' => 'Create Asset Maintenance',
|
||||
|
||||
@@ -309,7 +309,7 @@ return [
|
||||
'two_factor_enabled_edit_not_allowed' => 'Your administrator does not permit you to edit this setting.',
|
||||
'two_factor_enrollment_text' => "Two factor authentication is required, however your device has not been enrolled yet. Open your Google Authenticator app and scan the QR code below to enroll your device. Once you've enrolled your device, enter the code below",
|
||||
'require_accept_signature' => 'Require Signature',
|
||||
'require_accept_signature_help_text' => 'Enabling this feature will require users to physically sign off on accepting an asset.',
|
||||
'require_accept_signature_help_text' => 'Enabling this feature will require users to physically sign off on accepting items. This will override any category-specific signature requirements.',
|
||||
'require_checkinout_notes' => 'Require Notes on Checkin/Checkout',
|
||||
'require_checkinout_notes_help_text' => 'Enabling this feature will require the note fields to be populated when checking in or checking out an asset.',
|
||||
'left' => 'left',
|
||||
@@ -324,15 +324,30 @@ return [
|
||||
'username_format_help' => 'This setting will only be used by the import process if a username is not provided and we have to generate a username for you.',
|
||||
'oauth_title' => 'OAuth API Settings',
|
||||
'oauth_clients' => 'OAuth Clients',
|
||||
'oauth' => 'OAuth',
|
||||
'oauth_help' => 'Oauth Endpoint Settings',
|
||||
'oauth' => 'OAuth & API',
|
||||
'oauth_help' => 'Oauth Endpoint Settings and API tokens',
|
||||
'oauth_no_clients' => 'You have not created any OAuth clients yet.',
|
||||
'oauth_no_applications' => 'You have not created any Authorized Applications yet.',
|
||||
'oauth_secret' => 'Secret',
|
||||
'oauth_authorized_apps' => 'Authorized Applications',
|
||||
'oauth_redirect_url' => 'Redirect URL',
|
||||
'oauth_name_help' => ' Something your users will recognize and trust.',
|
||||
'oauth_scopes' => 'Scopes',
|
||||
'oauth_client_type' => 'Client Type',
|
||||
'oauth_client_type_oauth' => 'OAuth Client',
|
||||
'oauth_client_type_personal_access' => 'Personal Access Client',
|
||||
'oauth_client_type_password_grant' => 'Password Grant Client',
|
||||
'oauth_associated_token_count' => 'Token Count',
|
||||
'oauth_callback_url' => 'Your application authorization callback URL.',
|
||||
'oauth_personal_access_tokens' => 'User API Tokens (Personal Access Tokens)',
|
||||
'oauth_personal_access_tokens_none' => 'No personal access tokens found.',
|
||||
'oauth_client' => 'Client',
|
||||
'oauth_deleted_user' => 'Deleted user (ID: :id)',
|
||||
'oauth_token_status_revoked' => 'Revoked',
|
||||
'oauth_token_status_expired' => 'Expired',
|
||||
'oauth_token_status_active' => 'Active',
|
||||
'oauth_revoke' => 'Revoke',
|
||||
'oauth_unrevoke' => 'Unrevoke',
|
||||
'create_client' => 'Create Client',
|
||||
'no_scopes' => 'No scopes',
|
||||
'asset_tag_title' => 'Update Asset Tag Settings',
|
||||
@@ -346,6 +361,7 @@ return [
|
||||
'general_title' => 'Update General Settings',
|
||||
'mail_test' => 'Send Test',
|
||||
'mail_test_help' => 'This will attempt to send a test mail to :replyto.',
|
||||
'mail_test_no_email' => 'MAIL_REPLYTO_ADDR not set or has no value .env config file. Cannot send test email. Please update this value in your configuration file with a valid email address.',
|
||||
'filter_by_keyword' => 'Filter by setting keyword',
|
||||
'security' => 'Security',
|
||||
'security_title' => 'Update Security Settings',
|
||||
@@ -525,6 +541,7 @@ return [
|
||||
'purge' => 'permanently delete',
|
||||
'security' => 'password, passwords, requirements, two factor, two-factor, common passwords, remote login, logout, authentication',
|
||||
'notifications' => 'alerts, email, notifications, audit, threshold, email alerts, cc',
|
||||
'oauth' => 'oauth, oath, api, personal access keys, tokens',
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
@@ -56,4 +56,21 @@ return [
|
||||
'not_saved' => 'Your settings were not saved.',
|
||||
'mismatch' => 'There is 1 item in the database that need your attention before you can enable location scoping.|There are :count items in the database that need your attention before you can enable location scoping.',
|
||||
],
|
||||
'oauth' => [
|
||||
'token_revoked' => 'Personal access token revoked successfully.',
|
||||
'token_unrevoked' => 'Personal access token reinstated successfully.',
|
||||
'token_not_found' => 'That personal access token could not be found.',
|
||||
'token_revoke_error' => 'An error occurred while revoking the token.',
|
||||
'token_unrevoke_error' => 'An error occurred while reinstating the token.',
|
||||
'client_created' => 'OAuth client created successfully.',
|
||||
'client_updated' => 'OAuth client updated successfully.',
|
||||
'client_deleted' => 'OAuth client deleted successfully.',
|
||||
'client_revoked' => 'OAuth client revoked successfully.',
|
||||
'client_unrevoked' => 'OAuth client reinstated successfully.',
|
||||
'client_not_found' => 'That OAuth client could not be found.',
|
||||
'token_deleted' => 'Token revoked successfully.',
|
||||
'client_delete_denied' => 'You are not authorized to delete this client.',
|
||||
'client_edit_denied' => 'You are not authorized to edit this client.',
|
||||
'token_delete_denied' => 'You are not authorized to revoke this token.',
|
||||
],
|
||||
];
|
||||
|
||||
@@ -14,6 +14,8 @@ return [
|
||||
'filetype_info' => 'Allowed filetypes are png, gif, jpg, jpeg, doc, docx, pdf, txt, zip, and rar.',
|
||||
'history_user' => 'History for :name',
|
||||
'info' => 'Info',
|
||||
'send_acceptance_reminder' => 'Send Reminder',
|
||||
'unaccepted_items' => ':count Unaccepted Items',
|
||||
'restore_user' => 'Click here to restore them.',
|
||||
'last_login' => 'Last Login',
|
||||
'ldap_config_text' => 'The selected location will be set for ALL imported users. This will overwrite their existing location, and is an unusual use-case, so leaving this blank is typically best.',
|
||||
|
||||
@@ -15,6 +15,7 @@ return [
|
||||
'user_deleted_warning' => 'This user has been deleted. You will have to restore this user to edit them or assign them new assets.',
|
||||
'ldap_not_configured' => 'LDAP integration has not been configured for this installation.',
|
||||
'password_resets_sent' => 'The selected users who are activated and have a valid email addresses have been sent a password reset link.',
|
||||
'not_activated' => 'This user cannot login, so they cannot accept assets via email.',
|
||||
'password_reset_sent' => 'A password reset link has been sent to :email!',
|
||||
'user_has_no_email' => 'This user does not have an email address in their profile.',
|
||||
'log_record_not_found' => 'A matching log record for this user could not be found.',
|
||||
@@ -30,6 +31,7 @@ return [
|
||||
'unsuspend' => 'User was successfully unsuspended.',
|
||||
'restored' => 'User was successfully restored.',
|
||||
'import' => 'Users imported successfully.',
|
||||
'acceptance_reminder_sent' => 'Acceptance reminder sent for :count pending item.|Acceptance reminder sent for :count pending items.',
|
||||
],
|
||||
|
||||
'error' => [
|
||||
@@ -44,7 +46,7 @@ return [
|
||||
'delete_has_users_var' => 'This user still manages another user. Please select another manager for that user first.|This user still manages :count users. Please select another manager for them first.',
|
||||
'unsuspend' => 'There was an issue unsuspending the user. Please try again.',
|
||||
'import' => 'There was an issue importing users. Please try again.',
|
||||
'asset_already_accepted' => 'This asset has already been accepted.',
|
||||
'asset_already_accepted' => 'This item has already been accepted.',
|
||||
'accept_or_decline' => 'You must either accept or decline this asset.',
|
||||
'cannot_delete_yourself' => 'We would feel really bad if you deleted yourself, please reconsider.',
|
||||
'incorrect_user_accepted' => 'The asset you have attempted to accept was not checked out to you.',
|
||||
@@ -54,6 +56,7 @@ return [
|
||||
'ldap_could_not_get_entries' => 'Could not get entries from the LDAP server. Please check your LDAP server configuration in the LDAP config file. <br>Error from LDAP Server:',
|
||||
'password_ldap' => 'The password for this account is managed by LDAP/Active Directory. Please contact your IT department to change your password. ',
|
||||
'multi_company_items_assigned' => 'This user has items assigned that belong to a different company. Please check them in or edit their company.',
|
||||
'no_pending_acceptances' => 'This user has no pending acceptances to remind them about.',
|
||||
],
|
||||
|
||||
'deletefile' => [
|
||||
|
||||
@@ -54,7 +54,7 @@ return [
|
||||
'avatar_upload' => 'የተጫነ አምሳያ',
|
||||
'back' => 'ወደኋላ',
|
||||
'bad_data' => 'ምንም አልተገኘም። የተበላሸ ውሂብ ይሆን?',
|
||||
'bulkaudit' => 'የጅምላ ኦዲት',
|
||||
'bulkaudit' => 'Scanner Bulk Audit',
|
||||
'bulkaudit_status' => 'የኦዲት ሁኔታ',
|
||||
'bulk_checkout' => 'በጅምላ ማውጣት',
|
||||
'bulk_edit' => 'የጅምላ አርትዖት',
|
||||
@@ -122,7 +122,7 @@ return [
|
||||
'debug_warning_text' => 'This application is running in production mode with debugging enabled. This can expose sensitive data if your application is accessible to the outside world. Disable debug mode by setting the <code>APP_DEBUG</code> value in your <code>.env</code> file to <code>false</code>.',
|
||||
'delete' => 'Delete',
|
||||
'delete_confirm' => 'Are you sure you wish to delete :item?',
|
||||
'delete_confirm_no_undo' => 'Are you sure you wish to delete :item? This cannot be undone.',
|
||||
'delete_confirm_no_undo' => 'Are you sure, you wish to delete :item? This cannot be undone.',
|
||||
'deleted' => 'Deleted',
|
||||
'delete_seats' => 'Deleted Seats',
|
||||
'deletion_failed' => 'Deletion failed',
|
||||
@@ -154,7 +154,7 @@ return [
|
||||
'first_checkout' => '1<sup>st</sup> Checkout',
|
||||
'generate' => 'Generate',
|
||||
'generate_labels' => 'Generate Labels',
|
||||
'github_markdown' => 'This field accepts <a href="https://help.github.com/articles/github-flavored-markdown/">Github flavored markdown</a>.',
|
||||
'github_markdown' => 'This field accepts <a href="https://help.github.com/articles/github-flavored-markdown/" target="_blank">Github flavored markdown</a>.',
|
||||
'groups' => 'Groups',
|
||||
'gravatar_email' => 'Gravatar Email Address',
|
||||
'gravatar_url' => '<a href="http://gravatar.com"><small>Change your avatar at Gravatar.com</small></a>.',
|
||||
@@ -167,7 +167,7 @@ return [
|
||||
'image_upload' => 'Upload Image',
|
||||
'filetypes_accepted_help' => 'Accepted filetype is :types. The maximum size allowed is :size.|Accepted filetypes are :types. The maximum upload size allowed is :size.',
|
||||
'filetypes_size_help' => 'The maximum upload size allowed is :size.',
|
||||
'image_filetypes_help' => 'Accepted filetypes are jpg, webp, png, gif, svg, and avif. The maximum upload size allowed is :size.',
|
||||
'image_filetypes_help' => 'Accepted Filetypes are jpg, webp, png, gif, svg, and avif. The maximum upload size allowed is :size.',
|
||||
'unaccepted_image_type' => 'This image file was not readable. Accepted filetypes are jpg, webp, png, gif, and svg. The mimetype of this file is: :mimetype.',
|
||||
'import' => 'Import',
|
||||
'documentation' => 'Open documentation in a new link',
|
||||
@@ -224,6 +224,9 @@ return [
|
||||
'next_audit_date_help' => 'If you use auditing in your organization, this is usually automatically calculated based on the asset's last audit date and audit frequency (in <code>Admin Settings > Alerts</code>) and you can leave this blank. You can manually set this date here if you need to, but it must be later than the last audit date. ',
|
||||
'audit_images_help' => 'You can find audit images in the asset\'s history tab.',
|
||||
'no_email' => 'No email address associated with this user',
|
||||
'no_value' => 'No value',
|
||||
'device_eol' => 'Device EOL',
|
||||
'na' => 'N/A',
|
||||
'last_audit' => 'Last Audit',
|
||||
'new' => 'new!',
|
||||
'no_depreciation' => 'No Depreciation',
|
||||
@@ -271,7 +274,7 @@ return [
|
||||
'rtd' => 'Ready to Deploy',
|
||||
'requested_date' => 'Requested Date',
|
||||
'requested_assets' => 'Requested Assets',
|
||||
'requested_assets_menu' => 'Requested Items',
|
||||
'requested_assets_menu' => 'Requestable Items',
|
||||
'request_canceled' => 'Request Canceled',
|
||||
'request_item' => 'Request this item',
|
||||
'external_link_tooltip' => 'External link to',
|
||||
@@ -559,6 +562,11 @@ return [
|
||||
'error_user_company_accept_view' => 'An Asset assigned to you belongs to a different company so you can\'t accept nor deny it, please check with your manager',
|
||||
'error_assets_already_checked_out' => 'One or more of the assets are already checked out',
|
||||
'assigned_assets_removed' => 'The following were removed from the selected assets because they are already checked out',
|
||||
'upload_files' => 'Upload Files',
|
||||
'uploaded_files' => 'Uploaded Files',
|
||||
'sign_in_place' => 'Sign/Accept in place',
|
||||
'sign_in_place_help' => 'Check this box if you have the user present and wish for them to accept the item and sign/accept the EULA (when applicable) right now.',
|
||||
'unauthorized' => 'Unauthorized or unauthenticated.',
|
||||
'importer' => [
|
||||
'checked_out_to_fullname' => 'Checked Out to: Full Name',
|
||||
'checked_out_to_first_name' => 'Checked Out to: First Name',
|
||||
@@ -662,12 +670,16 @@ return [
|
||||
'child_locations' => 'Child Locations',
|
||||
'append' => 'Append',
|
||||
'optional' => 'OPTIONAL',
|
||||
'audit_by_field' => 'Audit by Field',
|
||||
'audit_by_field_help' => 'Auditing by scanning serial numbers is only an available option if serial numbers are required to be unique in the Admin Settings.',
|
||||
'audit_key' => 'ንብረት',
|
||||
|
||||
// Add form placeholders here
|
||||
'placeholders' => [
|
||||
'notes' => 'Add a note',
|
||||
],
|
||||
|
||||
'last_note' => 'Last Note',
|
||||
'bulk_delete_associations' => [
|
||||
'general_assoc_warning' => ':item_name still has associated items. Please remove them before deleting this :item.',
|
||||
'assoc_assets' => ':item_name is currently associated with :asset_count asset(s) and cannot be deleted. Please update your assets to no longer reference this :item and try again.',
|
||||
@@ -691,26 +703,6 @@ return [
|
||||
'checkin_item' => 'Checkin :name',
|
||||
],
|
||||
|
||||
'skins' => [
|
||||
'site_default' => 'Site Default',
|
||||
'default_blue' => 'Default Blue',
|
||||
'blue_dark' => 'Blue (Dark Mode)',
|
||||
'green' => 'Green',
|
||||
'green_dark' => 'Green (Dark Mode)',
|
||||
'red' => 'Red',
|
||||
'red_dark' => 'Red (Dark Mode)',
|
||||
'orange' => 'Orange',
|
||||
'orange_dark' => 'Orange (Dark Mode)',
|
||||
'black' => 'Black',
|
||||
'black_dark' => 'Black (Dark Mode)',
|
||||
'purple' => 'Purple',
|
||||
'purple_dark' => 'Purple (Dark Mode)',
|
||||
'yellow' => 'Yellow',
|
||||
'yellow_dark' => 'Yellow (Dark Mode)',
|
||||
'high_contrast' => 'High Contrast',
|
||||
|
||||
],
|
||||
|
||||
'select_all_none' => 'Select/Unselect All',
|
||||
'generic_model_not_found' => 'That :model was not found or you do not have permission to access it',
|
||||
'report_not_editable' => 'You do not have permission to edit this report template',
|
||||
@@ -754,4 +746,7 @@ return [
|
||||
|
||||
'months_plural' => '1 month|:count months',
|
||||
|
||||
'token_unrevoked' => 'API token reinstated',
|
||||
'token_revoked' => 'API token revoked',
|
||||
|
||||
];
|
||||
|
||||
@@ -90,7 +90,7 @@ return [
|
||||
'password' => 'Password',
|
||||
'password_reset' => 'Password Reset',
|
||||
'read_the_terms' => 'Please read the terms of use below.',
|
||||
'read_the_terms_and_click' => 'Please read the terms of use below, and click on the link at the bottom to confirm that you read and agree to the terms of use, and have received the asset.',
|
||||
'read_the_terms_and_click' => 'Please read the terms of use below, and click on the link at the bottom to confirm that you read and agree to the terms of use, and have received the item.',
|
||||
'click_here_to_review_terms_and_accept_item' => 'Click here to review the terms of use and accept the item|Click here to review the terms of use and accept the items',
|
||||
'requested' => 'Requested',
|
||||
'reset_link' => 'Your Password Reset Link',
|
||||
|
||||
@@ -107,8 +107,49 @@ return [
|
||||
],
|
||||
'accessoriesfiles' => [
|
||||
'name' => 'Manage Accessory Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with accessories.',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with accessories. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'assetsfiles' => [
|
||||
'name' => 'Manage Asset Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with assets. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'usersfiles' => [
|
||||
'name' => 'Manage User Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with users. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'modelsfiles' => [
|
||||
'name' => 'Manage Model Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with asset models on both the model view and the asset view screens. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'departmentsfiles' => [
|
||||
'name' => 'Manage Department Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with departments. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'suppliersfiles' => [
|
||||
'name' => 'Manage Supplier Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with suppliers. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'locationsfiles' => [
|
||||
'name' => 'Manage Location Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with locations.(This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'companiesfiles' => [
|
||||
'name' => 'Manage Company Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with companies. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'consumablesfiles' => [
|
||||
'name' => 'Manage Consumable Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with consumables. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'consumables' => [
|
||||
'name' => 'Consumables',
|
||||
'note' => 'Grants access to the Consumables section of the application.',
|
||||
@@ -129,10 +170,7 @@ return [
|
||||
'name' => 'Check Out Consumables',
|
||||
'note' => 'Assign consumables in inventory by checking them out.',
|
||||
],
|
||||
'consumablesfiles' => [
|
||||
'name' => 'Manage Consumable Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with consumables.',
|
||||
],
|
||||
|
||||
'licenses' => [
|
||||
'name' => 'Licenses',
|
||||
'note' => 'Grants access to the Licenses section of the application.',
|
||||
@@ -161,6 +199,11 @@ return [
|
||||
'name' => 'Manage License Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with licenses.',
|
||||
],
|
||||
'componentsfiles' => [
|
||||
'name' => 'Manage Component Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with components.',
|
||||
],
|
||||
|
||||
'licenseskeys' => [
|
||||
'name' => 'Manage License Keys',
|
||||
'note' => 'Allows the user to view product keys associated with licenses.',
|
||||
@@ -181,10 +224,7 @@ return [
|
||||
'componentsdelete' => [
|
||||
'name' => 'Delete Components',
|
||||
],
|
||||
'componentsfiles' => [
|
||||
'name' => 'Manage Component Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with components.',
|
||||
],
|
||||
|
||||
'componentscheckout' => [
|
||||
'name' => 'Check Out Components',
|
||||
'note' => 'Assign components in inventory by checking them out.',
|
||||
|
||||
@@ -9,7 +9,7 @@ return [
|
||||
'edit' => 'تعديل الملحق',
|
||||
'eula_text' => 'إتفاقية ترخيص المستخدم النهائي للتصنيف',
|
||||
'eula_text_help' => 'يسمح لك هذا الحقل بتخصيص مجموعة اتفاقيات ترخيص المستخدم لأنواع معينة من الأصول. اذا كنت تمتلك اتفاقية واحدة لجميع أصولك يمكنك أن تقوم بتأشير المربع في الأسفل لاستخدام الاتفاقية الافتراضية الاساسية.',
|
||||
'require_acceptance' => 'مطالبة المستخدمين بتأكيد قبولهم الأصول في هذا التصنيف.',
|
||||
'require_acceptance' => 'Require users to confirm acceptance of item in this category.',
|
||||
'no_default_eula' => 'لا يوجد هنالك اي (إتفاقية ترخيص المستخدم). قم باضافة واحدة من الإعدادات.',
|
||||
'total' => 'المجموع',
|
||||
'remaining' => 'المتاح',
|
||||
|
||||
@@ -17,6 +17,7 @@ return [
|
||||
'name' => 'اسم التصنيف',
|
||||
'require_acceptance' => 'مطالبة المستخدمين بتأكيد قبولهم للأصول في هذا التصنيف.',
|
||||
'required_acceptance' => 'سيتم إرسال رسالة إلكترونية تتضمن رابط إلى هذا المستخدم لتأكيد قبول هذا الأصل.',
|
||||
'global_signature_required_notice' => 'User signatures are currently required globally via the admin settings, so signatures will still be required regardless of this category setting if the item is checked out to a user (versus a location, etc).',
|
||||
'required_eula' => 'سيتم إرسال نسخة إلكترونية من إتفاقية الترخيص الى المستخدم',
|
||||
'no_default_eula' => 'لم يتم العثور على (اتفاقية ترخيص المستخدم) الأساسية. قم بإضافة واحدة من الإعدادات.',
|
||||
'update' => 'تحديث التصنيف',
|
||||
|
||||
@@ -5,7 +5,7 @@ return [
|
||||
'manage' => 'إدارة',
|
||||
'field' => 'حقل',
|
||||
'about_fieldsets_title' => 'حول مجموعة الحقول',
|
||||
'about_fieldsets_text' => '(مجموعات الحقول) تسمح لك بإنشاء مجموعات من الحقول اللتي يمكن إعادة إستخدامها مع موديل محدد.',
|
||||
'about_fieldsets_text' => 'مجموعات الحقول تسمح لك بإنشاء مجموعات من الحقول المخصصة التي يعاد استخدامها في كثير من الأحيان لأنواع معينة من نماذج الأصول.',
|
||||
'custom_format' => 'تنسيق Regex المخصص...',
|
||||
'encrypt_field' => 'تشفير قيمة هذا الحقل في قاعدة البيانات',
|
||||
'encrypt_field_help' => 'تحذير: تشفير الحقل يجعله غير قابل للبحث.',
|
||||
|
||||
@@ -7,5 +7,6 @@ return [
|
||||
'invalid_return_value' => 'القيمة غير صالحة العائدة من :name. توقّعت :expected، حصلت على :actual.',
|
||||
|
||||
'does_not_exist' => 'التسمية غير موجودة',
|
||||
|
||||
'use_new_label_engine_for_api' => 'Enable the New Label Engine to load labels via the API',
|
||||
'label_not_created' => 'Label object could not be created',
|
||||
];
|
||||
|
||||
@@ -8,7 +8,6 @@ return [
|
||||
'assoc_child_loc' => 'هذا الموقع هو حاليا أحد الوالدين لموقع طفل واحد على الأقل ولا يمكن حذفه. يرجى تحديث مواقعك لم تعد تشير إلى هذا الموقع ثم أعد المحاولة.',
|
||||
'assigned_assets' => 'الأصول المعينة',
|
||||
'current_location' => 'الموقع الحالي',
|
||||
'open_map' => 'Open in :map_provider_icon Maps',
|
||||
'deleted_warning' => 'This location has been deleted. Please restore it before attempting to make any changes.',
|
||||
|
||||
'create' => [
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
return [
|
||||
'select_type' => 'Select Maintenance Type',
|
||||
'asset_maintenance_type' => 'نوعر صيانة الأصل',
|
||||
'asset_maintenance_type' => 'اكتب',
|
||||
'title' => 'المسمى الوظيفي',
|
||||
'start_date' => 'تاريخ البداية',
|
||||
'completion_date' => 'تاريخ الانتهاء',
|
||||
'cost' => 'التكلفة',
|
||||
'is_warranty' => 'تحسين الضمان',
|
||||
'asset_maintenance_time' => 'وقت صيانة الاصل (بالايام)',
|
||||
'asset_maintenance_time' => 'Duration',
|
||||
'notes' => 'مُلاحظات',
|
||||
'update' => 'تعديل صيانة الأصل',
|
||||
'create' => 'إنشاء صيانة الأصول',
|
||||
|
||||
@@ -309,7 +309,7 @@ return [
|
||||
'two_factor_enabled_edit_not_allowed' => 'لا يسمح لك المشرف بتعديل هذا الإعداد.',
|
||||
'two_factor_enrollment_text' => 'التوثيق ذو العاملين 2FA اجباري، ولكن لم يتم تسجيل جهازك بعد. افتح تطبيق غوغل للتوثيق Google Authenticator وافحص رمز الاستجابة السريعة QR أدناه لتسجيل جهازك. بعد تسجيل جهازك، أدخل الرمز أدناه',
|
||||
'require_accept_signature' => 'يتطلب التوقيع',
|
||||
'require_accept_signature_help_text' => 'سيتطلب تمكين هذه الميزة من المستخدمين تسجيل الدخول فعليا عند قبول مادة العرض.',
|
||||
'require_accept_signature_help_text' => 'Enabling this feature will require users to physically sign off on accepting items. This will override any category-specific signature requirements.',
|
||||
'require_checkinout_notes' => 'Require Notes on Checkin/Checkout',
|
||||
'require_checkinout_notes_help_text' => 'Enabling this feature will require the note fields to be populated when checking in or checking out an asset.',
|
||||
'left' => 'اليسار',
|
||||
@@ -324,15 +324,30 @@ return [
|
||||
'username_format_help' => 'سيتم استخدام هذا الإعداد فقط من قبل عملية الاستيراد إذا لم يتم توفير اسم المستخدم ويتعين علينا إنشاء اسم مستخدم لك.',
|
||||
'oauth_title' => 'إعدادات API OAuth',
|
||||
'oauth_clients' => 'OAuth Clients',
|
||||
'oauth' => 'OAuth',
|
||||
'oauth_help' => 'إعدادات نقطة النهاية Oauth',
|
||||
'oauth' => 'OAuth & API',
|
||||
'oauth_help' => 'Oauth Endpoint Settings and API tokens',
|
||||
'oauth_no_clients' => 'You have not created any OAuth clients yet.',
|
||||
'oauth_no_applications' => 'You have not created any Authorized Applications yet.',
|
||||
'oauth_secret' => 'Secret',
|
||||
'oauth_authorized_apps' => 'Authorized Applications',
|
||||
'oauth_redirect_url' => 'Redirect URL',
|
||||
'oauth_name_help' => ' Something your users will recognize and trust.',
|
||||
'oauth_scopes' => 'Scopes',
|
||||
'oauth_client_type' => 'Client Type',
|
||||
'oauth_client_type_oauth' => 'OAuth Client',
|
||||
'oauth_client_type_personal_access' => 'Personal Access Client',
|
||||
'oauth_client_type_password_grant' => 'Password Grant Client',
|
||||
'oauth_associated_token_count' => 'Token Count',
|
||||
'oauth_callback_url' => 'Your application authorization callback URL.',
|
||||
'oauth_personal_access_tokens' => 'User API Tokens (Personal Access Tokens)',
|
||||
'oauth_personal_access_tokens_none' => 'No personal access tokens found.',
|
||||
'oauth_client' => 'Client',
|
||||
'oauth_deleted_user' => 'Deleted user (ID: :id)',
|
||||
'oauth_token_status_revoked' => 'Revoked',
|
||||
'oauth_token_status_expired' => 'Expired',
|
||||
'oauth_token_status_active' => 'نشط',
|
||||
'oauth_revoke' => 'Revoke',
|
||||
'oauth_unrevoke' => 'Unrevoke',
|
||||
'create_client' => 'Create Client',
|
||||
'no_scopes' => 'No scopes',
|
||||
'asset_tag_title' => 'تحديث إعدادات علامة الأصل',
|
||||
@@ -346,6 +361,7 @@ return [
|
||||
'general_title' => 'تحديث الإعدادات العامة',
|
||||
'mail_test' => 'إرسال اختبار',
|
||||
'mail_test_help' => 'هذا سيحاول إرسال بريد تجريبي إلى :replyto.',
|
||||
'mail_test_no_email' => 'MAIL_REPLYTO_ADDR not set or has no value .env config file. Cannot send test email. Please update this value in your configuration file with a valid email address.',
|
||||
'filter_by_keyword' => 'تصفية عن طريق إعداد الكلمة المفتاحية',
|
||||
'security' => 'أمان',
|
||||
'security_title' => 'تحديث إعدادات الأمان',
|
||||
@@ -525,6 +541,7 @@ return [
|
||||
'purge' => 'حذف نهائيًا',
|
||||
'security' => 'كلمة المرور، كلمة المرور، كلمات المرور، المتطلبات، عاملان، كلمات المرور الشائعة، تسجيل الدخول، المصادقة',
|
||||
'notifications' => 'alerts, email, notifications, audit, threshold, email alerts, cc',
|
||||
'oauth' => 'oauth, oath, api, personal access keys, tokens',
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
@@ -56,4 +56,21 @@ return [
|
||||
'not_saved' => 'Your settings were not saved.',
|
||||
'mismatch' => 'There is 1 item in the database that need your attention before you can enable location scoping.|There are :count items in the database that need your attention before you can enable location scoping.',
|
||||
],
|
||||
'oauth' => [
|
||||
'token_revoked' => 'Personal access token revoked successfully.',
|
||||
'token_unrevoked' => 'Personal access token reinstated successfully.',
|
||||
'token_not_found' => 'That personal access token could not be found.',
|
||||
'token_revoke_error' => 'An error occurred while revoking the token.',
|
||||
'token_unrevoke_error' => 'An error occurred while reinstating the token.',
|
||||
'client_created' => 'OAuth client created successfully.',
|
||||
'client_updated' => 'OAuth client updated successfully.',
|
||||
'client_deleted' => 'OAuth client deleted successfully.',
|
||||
'client_revoked' => 'OAuth client revoked successfully.',
|
||||
'client_unrevoked' => 'OAuth client reinstated successfully.',
|
||||
'client_not_found' => 'That OAuth client could not be found.',
|
||||
'token_deleted' => 'Token revoked successfully.',
|
||||
'client_delete_denied' => 'You are not authorized to delete this client.',
|
||||
'client_edit_denied' => 'You are not authorized to edit this client.',
|
||||
'token_delete_denied' => 'You are not authorized to revoke this token.',
|
||||
],
|
||||
];
|
||||
|
||||
@@ -14,6 +14,8 @@ return [
|
||||
'filetype_info' => 'انواع صيغ الملفات المسوح بها هي png, gif, jpg, jpeg, doc, docx, pdf, txt, zip, and rar.',
|
||||
'history_user' => 'الأرشيف الخاص بـ :name',
|
||||
'info' => 'معلومات',
|
||||
'send_acceptance_reminder' => 'Send Reminder',
|
||||
'unaccepted_items' => ':count Unaccepted Items',
|
||||
'restore_user' => 'انقر هنا لاستعادتها.',
|
||||
'last_login' => 'آخر دخول للمستخدم',
|
||||
'ldap_config_text' => 'The selected location will be set for ALL imported users. This will overwrite their existing location, and is an unusual use-case, so leaving this blank is typically best.',
|
||||
|
||||
@@ -15,6 +15,7 @@ return [
|
||||
'user_deleted_warning' => 'تم حذف المستخدم. سيكون عليك استعادة هذا المستخدم اذا ارت التعديل عليه او تسليمه اجهزة جديدة.',
|
||||
'ldap_not_configured' => 'لم يتم تكوين دمج لداب لهذا التثبيت.',
|
||||
'password_resets_sent' => 'تم إرسال رابط إعادة تعيين كلمة المرور للمستخدمين المحددين الذين تم تفعيلهم ولديهم عناوين بريد إلكتروني صالحة.',
|
||||
'not_activated' => 'This user cannot login, so they cannot accept assets via email.',
|
||||
'password_reset_sent' => 'تم إرسال رابط إعادة تعيين كلمة المرور إلى البريد الإلكتروني!',
|
||||
'user_has_no_email' => 'هذا المستخدم ليس لديه عنوان بريد إلكتروني في ملفه الشخصي.',
|
||||
'log_record_not_found' => 'تعذر العثور على سجل مطابق لهذا المستخدم.',
|
||||
@@ -30,6 +31,7 @@ return [
|
||||
'unsuspend' => 'تم إلغاء التعليق عن المستخدم بنجاح.',
|
||||
'restored' => 'تم استعادة المستخدم بنجاح.',
|
||||
'import' => 'تم استيراد المستخدمين بنجاح.',
|
||||
'acceptance_reminder_sent' => 'Acceptance reminder sent for :count pending item.|Acceptance reminder sent for :count pending items.',
|
||||
],
|
||||
|
||||
'error' => [
|
||||
@@ -44,7 +46,7 @@ return [
|
||||
'delete_has_users_var' => 'This user still manages another user. Please select another manager for that user first.|This user still manages :count users. Please select another manager for them first.',
|
||||
'unsuspend' => 'حدث خطأ ما أثناء إلغاء تقييد الانتظار. حاول مرة أخرى.',
|
||||
'import' => 'حدث خطأ أثناء استيراد المستخدمين. حاول مرة أخرى.',
|
||||
'asset_already_accepted' => 'هذا الجهاز تم قبوله مسبقاً.',
|
||||
'asset_already_accepted' => 'This item has already been accepted.',
|
||||
'accept_or_decline' => 'يجب إما قبول مادة العرض هذه أو رفضها.',
|
||||
'cannot_delete_yourself' => 'We would feel really bad if you deleted yourself, please reconsider.',
|
||||
'incorrect_user_accepted' => 'لم يتم سحب مادة العرض التي حاولت قبولها.',
|
||||
@@ -54,6 +56,7 @@ return [
|
||||
'ldap_could_not_get_entries' => 'تعذر الحصول على إدخالات من خادم LDAP. الرجاء التحقق من الاعدادات الخاصة بخادم LDAP في ملف اعدادات LDAP. <br>الخطأ من خادم LDAP:',
|
||||
'password_ldap' => 'تتم إدارة كلمة المرور لهذا الحساب بواسطة لداب / أكتيف ديركتوري. يرجى الاتصال بقسم تقنية المعلومات لتغيير كلمة المرور.',
|
||||
'multi_company_items_assigned' => 'This user has items assigned that belong to a different company. Please check them in or edit their company.',
|
||||
'no_pending_acceptances' => 'This user has no pending acceptances to remind them about.',
|
||||
],
|
||||
|
||||
'deletefile' => [
|
||||
|
||||
@@ -54,7 +54,7 @@ return [
|
||||
'avatar_upload' => 'رفع صورة رمزية',
|
||||
'back' => 'الرجوع للخلف',
|
||||
'bad_data' => 'لم يتم العثور على شيء. ربما البيانات السيئة؟',
|
||||
'bulkaudit' => 'تدقيق متعدد',
|
||||
'bulkaudit' => 'Scanner Bulk Audit',
|
||||
'bulkaudit_status' => 'حالة التدقيق',
|
||||
'bulk_checkout' => 'اخراج متعدد',
|
||||
'bulk_edit' => 'تحرير بالجملة',
|
||||
@@ -122,7 +122,7 @@ return [
|
||||
'debug_warning_text' => 'هذا التطبيق يعمل في وضع الإنتاج مع تمكين التصحيح. هذا يمكن أن يعرض البيانات الحساسة إذا كان التطبيق الخاص بك هو في متناول العالم الخارجي. تعطيل وضع التصحيح عن طريق تعيين قيمة <code>APP_DEBUG</code> في ملف <code>.env</code> إلى <code>false</code>.',
|
||||
'delete' => 'حذف',
|
||||
'delete_confirm' => 'هل أنت متأكد من حذف :المنتج؟',
|
||||
'delete_confirm_no_undo' => 'Are you sure you wish to delete :item? This cannot be undone.',
|
||||
'delete_confirm_no_undo' => 'هل أنت متأكد من أنك ترغب في حذف :item؟ لا يمكن التراجع بعد الحذف.',
|
||||
'deleted' => 'تم حذفها',
|
||||
'delete_seats' => 'المقاعد المحذوفة',
|
||||
'deletion_failed' => 'فشل الحذف',
|
||||
@@ -154,7 +154,7 @@ return [
|
||||
'first_checkout' => '1<sup>st</sup> Checkout',
|
||||
'generate' => 'توفير',
|
||||
'generate_labels' => 'إنشاء تسميات',
|
||||
'github_markdown' => 'يتيح هذا الحقل <a href="https://help.github.com/articles/github-flavored-markdown/">بتطبيق نمط الكتابة من Github</a>.',
|
||||
'github_markdown' => 'This field accepts <a href="https://help.github.com/articles/github-flavored-markdown/" target="_blank">Github flavored markdown</a>.',
|
||||
'groups' => 'المجموعات',
|
||||
'gravatar_email' => 'البريد الإلكتروني لخدمة Gravatar',
|
||||
'gravatar_url' => '<a href="http://gravatar.com"><small>غيّر صورتك الرمزية في Gravatar.com</small></a>.',
|
||||
@@ -167,7 +167,7 @@ return [
|
||||
'image_upload' => 'رفع صورة',
|
||||
'filetypes_accepted_help' => 'Accepted filetype is :types. The maximum size allowed is :size.|Accepted filetypes are :types. The maximum upload size allowed is :size.',
|
||||
'filetypes_size_help' => 'الحد الأقصى المسموح لحجم التصعيد هو :size.',
|
||||
'image_filetypes_help' => 'Accepted filetypes are jpg, webp, png, gif, svg, and avif. The maximum upload size allowed is :size.',
|
||||
'image_filetypes_help' => 'أنواع الملفات المسموحة هي jpg، webpp، png، gif، svg، tif. الحد الأقصى لحجم التصعيد المسموح به هو :size.',
|
||||
'unaccepted_image_type' => 'ملف الصورة هذا غير قابل للقراءة. أنواع الملفات المقبولة هي jpg، webpp، png، gif، svg. نوع هذا الملف هو: :mimetype.',
|
||||
'import' => 'استيراد',
|
||||
'documentation' => 'Open documentation in a new link',
|
||||
@@ -224,6 +224,9 @@ return [
|
||||
'next_audit_date_help' => 'If you use auditing in your organization, this is usually automatically calculated based on the asset's last audit date and audit frequency (in <code>Admin Settings > Alerts</code>) and you can leave this blank. You can manually set this date here if you need to, but it must be later than the last audit date. ',
|
||||
'audit_images_help' => 'يمكنك العثور على صور التدقيق في علامة تبويب التاريخ في صفحة الأصول.',
|
||||
'no_email' => 'لا يوجد عنوان بريد إلكتروني مرتبط بهذا المستخدم',
|
||||
'no_value' => 'No value',
|
||||
'device_eol' => 'Device EOL',
|
||||
'na' => 'N/A',
|
||||
'last_audit' => 'آخر مراجعة',
|
||||
'new' => 'الجديد!',
|
||||
'no_depreciation' => 'لا يوجد إستهلاك',
|
||||
@@ -271,7 +274,7 @@ return [
|
||||
'rtd' => 'جاهزة للتوزيع',
|
||||
'requested_date' => 'تاريخ الطلب',
|
||||
'requested_assets' => 'الأصول المطلوبة',
|
||||
'requested_assets_menu' => 'Requested Items',
|
||||
'requested_assets_menu' => 'العناصر المطلوبة',
|
||||
'request_canceled' => 'تم إلغاء الطلب',
|
||||
'request_item' => 'طلب هذا العنصر',
|
||||
'external_link_tooltip' => 'رابط خارجي إلى',
|
||||
@@ -559,6 +562,11 @@ return [
|
||||
'error_user_company_accept_view' => 'الأصل الذي تم تعيينه لك ينتمي إلى شركة أخرى لذلك لا يمكنك قبوله أو رفضه، يرجى التحقق من المدير الخاص بك',
|
||||
'error_assets_already_checked_out' => 'One or more of the assets are already checked out',
|
||||
'assigned_assets_removed' => 'The following were removed from the selected assets because they are already checked out',
|
||||
'upload_files' => 'Upload Files',
|
||||
'uploaded_files' => 'Uploaded Files',
|
||||
'sign_in_place' => 'Sign/Accept in place',
|
||||
'sign_in_place_help' => 'Check this box if you have the user present and wish for them to accept the item and sign/accept the EULA (when applicable) right now.',
|
||||
'unauthorized' => 'Unauthorized or unauthenticated.',
|
||||
'importer' => [
|
||||
'checked_out_to_fullname' => 'تم الخروج إلى: الاسم الكامل',
|
||||
'checked_out_to_first_name' => 'تم الخروج إلى: الاسم الأول',
|
||||
@@ -662,12 +670,16 @@ return [
|
||||
'child_locations' => 'Child Locations',
|
||||
'append' => 'إلحاق',
|
||||
'optional' => 'OPTIONAL',
|
||||
'audit_by_field' => 'Audit by Field',
|
||||
'audit_by_field_help' => 'Auditing by scanning serial numbers is only an available option if serial numbers are required to be unique in the Admin Settings.',
|
||||
'audit_key' => 'أصل',
|
||||
|
||||
// Add form placeholders here
|
||||
'placeholders' => [
|
||||
'notes' => 'Add a note',
|
||||
],
|
||||
|
||||
'last_note' => 'Last Note',
|
||||
'bulk_delete_associations' => [
|
||||
'general_assoc_warning' => ':item_name still has associated items. Please remove them before deleting this :item.',
|
||||
'assoc_assets' => ':item_name is currently associated with :asset_count asset(s) and cannot be deleted. Please update your assets to no longer reference this :item and try again.',
|
||||
@@ -691,26 +703,6 @@ return [
|
||||
'checkin_item' => 'Checkin :name',
|
||||
],
|
||||
|
||||
'skins' => [
|
||||
'site_default' => 'Site Default',
|
||||
'default_blue' => 'Default Blue',
|
||||
'blue_dark' => 'Blue (Dark Mode)',
|
||||
'green' => 'Green',
|
||||
'green_dark' => 'Green (Dark Mode)',
|
||||
'red' => 'Red',
|
||||
'red_dark' => 'Red (Dark Mode)',
|
||||
'orange' => 'Orange',
|
||||
'orange_dark' => 'Orange (Dark Mode)',
|
||||
'black' => 'Black',
|
||||
'black_dark' => 'Black (Dark Mode)',
|
||||
'purple' => 'Purple',
|
||||
'purple_dark' => 'Purple (Dark Mode)',
|
||||
'yellow' => 'Yellow',
|
||||
'yellow_dark' => 'Yellow (Dark Mode)',
|
||||
'high_contrast' => 'High Contrast',
|
||||
|
||||
],
|
||||
|
||||
'select_all_none' => 'Select/Unselect All',
|
||||
'generic_model_not_found' => 'That :model was not found or you do not have permission to access it',
|
||||
'report_not_editable' => 'You do not have permission to edit this report template',
|
||||
@@ -754,4 +746,7 @@ return [
|
||||
|
||||
'months_plural' => '1 month|:count months',
|
||||
|
||||
'token_unrevoked' => 'API token reinstated',
|
||||
'token_revoked' => 'API token revoked',
|
||||
|
||||
];
|
||||
|
||||
@@ -90,7 +90,7 @@ return [
|
||||
'password' => 'كلمة المرور',
|
||||
'password_reset' => 'إعادة تعيين كلمة المرور',
|
||||
'read_the_terms' => 'يرجى قراءة شروط الاستخدام أدناه.',
|
||||
'read_the_terms_and_click' => 'يرجى قراءة شروط الاستخدام أدناه، وانقر على الرابط في الأسفل لتأكيد أنك تقرأ وتوافق على شروط الاستخدام، وقد استلمت الأصل.',
|
||||
'read_the_terms_and_click' => 'Please read the terms of use below, and click on the link at the bottom to confirm that you read and agree to the terms of use, and have received the item.',
|
||||
'click_here_to_review_terms_and_accept_item' => 'Click here to review the terms of use and accept the item|Click here to review the terms of use and accept the items',
|
||||
'requested' => 'طلب',
|
||||
'reset_link' => 'رابط إعادة تعيين كلمة المرور',
|
||||
|
||||
@@ -107,8 +107,49 @@ return [
|
||||
],
|
||||
'accessoriesfiles' => [
|
||||
'name' => 'Manage Accessory Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with accessories.',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with accessories. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'assetsfiles' => [
|
||||
'name' => 'Manage Asset Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with assets. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'usersfiles' => [
|
||||
'name' => 'Manage User Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with users. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'modelsfiles' => [
|
||||
'name' => 'Manage Model Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with asset models on both the model view and the asset view screens. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'departmentsfiles' => [
|
||||
'name' => 'Manage Department Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with departments. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'suppliersfiles' => [
|
||||
'name' => 'Manage Supplier Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with suppliers. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'locationsfiles' => [
|
||||
'name' => 'Manage Location Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with locations.(This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'companiesfiles' => [
|
||||
'name' => 'Manage Company Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with companies. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'consumablesfiles' => [
|
||||
'name' => 'Manage Consumable Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with consumables. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'consumables' => [
|
||||
'name' => 'المواد الاستهلاكية',
|
||||
'note' => 'Grants access to the Consumables section of the application.',
|
||||
@@ -129,10 +170,7 @@ return [
|
||||
'name' => 'Check Out Consumables',
|
||||
'note' => 'Assign consumables in inventory by checking them out.',
|
||||
],
|
||||
'consumablesfiles' => [
|
||||
'name' => 'Manage Consumable Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with consumables.',
|
||||
],
|
||||
|
||||
'licenses' => [
|
||||
'name' => 'التراخيص',
|
||||
'note' => 'Grants access to the Licenses section of the application.',
|
||||
@@ -161,6 +199,11 @@ return [
|
||||
'name' => 'Manage License Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with licenses.',
|
||||
],
|
||||
'componentsfiles' => [
|
||||
'name' => 'Manage Component Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with components.',
|
||||
],
|
||||
|
||||
'licenseskeys' => [
|
||||
'name' => 'Manage License Keys',
|
||||
'note' => 'Allows the user to view product keys associated with licenses.',
|
||||
@@ -181,10 +224,7 @@ return [
|
||||
'componentsdelete' => [
|
||||
'name' => 'Delete Components',
|
||||
],
|
||||
'componentsfiles' => [
|
||||
'name' => 'Manage Component Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with components.',
|
||||
],
|
||||
|
||||
'componentscheckout' => [
|
||||
'name' => 'Check Out Components',
|
||||
'note' => 'Assign components in inventory by checking them out.',
|
||||
|
||||
@@ -9,7 +9,7 @@ return [
|
||||
'edit' => 'Редактиране на аксесоар',
|
||||
'eula_text' => 'EULA на категорията',
|
||||
'eula_text_help' => 'Това поле позволява да задавате различни EULA за всеки тип активи. Ако имате обща EULA за всички активи, можете да използвате кутийката по-долу за да използвате една обща по подразбиране.',
|
||||
'require_acceptance' => 'Задължаване на потребителите да потвърждават приемането на активи от тази категория.',
|
||||
'require_acceptance' => 'Require users to confirm acceptance of item in this category.',
|
||||
'no_default_eula' => 'Няма EULA по подразбиране. Добавете я в Настройки.',
|
||||
'total' => 'Oбщо',
|
||||
'remaining' => 'Наличност',
|
||||
|
||||
@@ -17,6 +17,7 @@ return [
|
||||
'name' => 'Име на категория',
|
||||
'require_acceptance' => 'Задължаване на потребителите да потвърждават приемането на активи от тази категория.',
|
||||
'required_acceptance' => 'Потребителят ще получи email с връзка за потвърждаване получаването на актива.',
|
||||
'global_signature_required_notice' => 'User signatures are currently required globally via the admin settings, so signatures will still be required regardless of this category setting if the item is checked out to a user (versus a location, etc).',
|
||||
'required_eula' => 'Потребителят ще получи копие на EULA.',
|
||||
'no_default_eula' => 'Няма EULA по подразбиране. Добавете я в Настройки.',
|
||||
'update' => 'Обновяване на категория',
|
||||
|
||||
@@ -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' => 'ВНИМАНИЕ: Шифроване на поле го прави невалидно за търсене.',
|
||||
|
||||
@@ -7,5 +7,6 @@ return [
|
||||
'invalid_return_value' => 'Невалидна стойност от :name. Очакван :expected, получен :actual.',
|
||||
|
||||
'does_not_exist' => 'Етикета не съществува',
|
||||
|
||||
'use_new_label_engine_for_api' => 'Enable the New Label Engine to load labels via the API',
|
||||
'label_not_created' => 'Label object could not be created',
|
||||
];
|
||||
|
||||
@@ -8,7 +8,6 @@ return [
|
||||
'assoc_child_loc' => 'В избраното местоположение е присъединено едно или повече местоположения. Моля преместете ги в друго и опитайте отново.',
|
||||
'assigned_assets' => 'Изписани Активи',
|
||||
'current_location' => 'Текущо местоположение',
|
||||
'open_map' => 'Отвори в :map_provider_icon карти',
|
||||
'deleted_warning' => 'Това местоположение е изтрито. Моля възстановете го преди да правите промени.',
|
||||
|
||||
'create' => [
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
return [
|
||||
'select_type' => 'Изберете тип поддръжка',
|
||||
'asset_maintenance_type' => 'Тип на поддръжка на актив',
|
||||
'asset_maintenance_type' => 'Тип',
|
||||
'title' => 'Титла',
|
||||
'start_date' => 'Начална дата',
|
||||
'completion_date' => 'Крайна дата',
|
||||
'cost' => 'Стойност',
|
||||
'is_warranty' => 'Подобрение на гаранцията',
|
||||
'asset_maintenance_time' => 'Време за поддръжка на актив (в дни)',
|
||||
'asset_maintenance_time' => 'Duration',
|
||||
'notes' => 'Бележки',
|
||||
'update' => 'Обнови поддръжката на актив',
|
||||
'create' => 'Създаване на поддръжка на актив',
|
||||
|
||||
@@ -309,7 +309,7 @@ return [
|
||||
'two_factor_enabled_edit_not_allowed' => 'Вашият администратор не разрешава да редактирате тази настройка.',
|
||||
'two_factor_enrollment_text' => 'Двуфакторово удостоверяване се изисква, но вашето устройство не е било регистрирано още. Отворете Google Authenticator и сканирайте QR кода по-долу за да регистрирате вашето устройство. След като сте записани вашето устройство, въведете кода по-долу',
|
||||
'require_accept_signature' => 'Изисква подпис',
|
||||
'require_accept_signature_help_text' => 'Разрешаването на тази функция ще изисква от потребителите да се подпишат физически за приемане на даден актив.',
|
||||
'require_accept_signature_help_text' => 'Enabling this feature will require users to physically sign off on accepting items. This will override any category-specific signature requirements.',
|
||||
'require_checkinout_notes' => 'Изисквай бележки при изписване/вписване',
|
||||
'require_checkinout_notes_help_text' => 'Включвайки тази опция ще изисква полето бележки да бъде попълнено, когато изписвате или вписвате актив.',
|
||||
'left' => 'ляво',
|
||||
@@ -324,15 +324,30 @@ return [
|
||||
'username_format_help' => 'Тази настройка се изпозлва само при импортиране, ако потребителя не е въведен и ние трябва да му генерираме потребителско име.',
|
||||
'oauth_title' => 'OAuth API Настройки',
|
||||
'oauth_clients' => 'OAuth Клиенти',
|
||||
'oauth' => 'OAuth',
|
||||
'oauth_help' => 'Oauth Endpoint настройки',
|
||||
'oauth' => 'OAuth & API',
|
||||
'oauth_help' => 'Oauth Endpoint Settings and API tokens',
|
||||
'oauth_no_clients' => 'Все още не сте създали OAuth клиенти.',
|
||||
'oauth_no_applications' => 'You have not created any Authorized Applications yet.',
|
||||
'oauth_secret' => 'Тайна',
|
||||
'oauth_authorized_apps' => 'Оторизирани приложения',
|
||||
'oauth_redirect_url' => 'URL адрес за пренасочване',
|
||||
'oauth_name_help' => ' Нещо, на което вашите потребители ще разпознаят и ще се доверят.',
|
||||
'oauth_scopes' => 'Обхват',
|
||||
'oauth_client_type' => 'Client Type',
|
||||
'oauth_client_type_oauth' => 'OAuth Client',
|
||||
'oauth_client_type_personal_access' => 'Personal Access Client',
|
||||
'oauth_client_type_password_grant' => 'Password Grant Client',
|
||||
'oauth_associated_token_count' => 'Token Count',
|
||||
'oauth_callback_url' => 'Вашият URL адрес за обратно извикване за оторизация.',
|
||||
'oauth_personal_access_tokens' => 'User API Tokens (Personal Access Tokens)',
|
||||
'oauth_personal_access_tokens_none' => 'No personal access tokens found.',
|
||||
'oauth_client' => 'Client',
|
||||
'oauth_deleted_user' => 'Deleted user (ID: :id)',
|
||||
'oauth_token_status_revoked' => 'Revoked',
|
||||
'oauth_token_status_expired' => 'Expired',
|
||||
'oauth_token_status_active' => 'Активен',
|
||||
'oauth_revoke' => 'Revoke',
|
||||
'oauth_unrevoke' => 'Unrevoke',
|
||||
'create_client' => 'Създайте клиент',
|
||||
'no_scopes' => 'Без обхват',
|
||||
'asset_tag_title' => 'Обнови настроките на етикета на актива',
|
||||
@@ -346,6 +361,7 @@ return [
|
||||
'general_title' => 'Обнови общите настройки',
|
||||
'mail_test' => 'Изпрати Тест',
|
||||
'mail_test_help' => 'Изпрати тестов е-майл до :replyto.',
|
||||
'mail_test_no_email' => 'MAIL_REPLYTO_ADDR not set or has no value .env config file. Cannot send test email. Please update this value in your configuration file with a valid email address.',
|
||||
'filter_by_keyword' => 'Филтър по ключова дума',
|
||||
'security' => 'Сигурност',
|
||||
'security_title' => 'Обнови настройките за сигурност',
|
||||
@@ -525,6 +541,7 @@ return [
|
||||
'purge' => 'изтриване за постоянно',
|
||||
'security' => 'парола, парили, изисквания, двустепенна идентификация, двустепенна-идентификация, общи пароли, отдалечен вход, изход, идентификация',
|
||||
'notifications' => 'аларми, е-майл, известия, одит, праг, е-майл аларми, сс',
|
||||
'oauth' => 'oauth, oath, api, personal access keys, tokens',
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
@@ -56,4 +56,21 @@ return [
|
||||
'not_saved' => 'Вашите настройки не бяха записани.',
|
||||
'mismatch' => 'В базата данни има 1 елемент, който изисква вашето внимание, преди да можете да активирате обхвата на местоположението.|В базата данни има :count елементи, които изискват вашето внимание, преди да можете да активирате обхвата на местоположението.',
|
||||
],
|
||||
'oauth' => [
|
||||
'token_revoked' => 'Personal access token revoked successfully.',
|
||||
'token_unrevoked' => 'Personal access token reinstated successfully.',
|
||||
'token_not_found' => 'That personal access token could not be found.',
|
||||
'token_revoke_error' => 'An error occurred while revoking the token.',
|
||||
'token_unrevoke_error' => 'An error occurred while reinstating the token.',
|
||||
'client_created' => 'OAuth client created successfully.',
|
||||
'client_updated' => 'OAuth client updated successfully.',
|
||||
'client_deleted' => 'OAuth client deleted successfully.',
|
||||
'client_revoked' => 'OAuth client revoked successfully.',
|
||||
'client_unrevoked' => 'OAuth client reinstated successfully.',
|
||||
'client_not_found' => 'That OAuth client could not be found.',
|
||||
'token_deleted' => 'Token revoked successfully.',
|
||||
'client_delete_denied' => 'You are not authorized to delete this client.',
|
||||
'client_edit_denied' => 'You are not authorized to edit this client.',
|
||||
'token_delete_denied' => 'You are not authorized to revoke this token.',
|
||||
],
|
||||
];
|
||||
|
||||
@@ -14,6 +14,8 @@ return [
|
||||
'filetype_info' => 'Позволените типове файлове са png, gif, jpg, jpeg, doc, docx, pdf, txt, zip, и rar.',
|
||||
'history_user' => 'История за :name',
|
||||
'info' => 'Информация',
|
||||
'send_acceptance_reminder' => 'Send Reminder',
|
||||
'unaccepted_items' => ':count Unaccepted Items',
|
||||
'restore_user' => 'Кликнете тук, за да ги възстановите.',
|
||||
'last_login' => 'Последен достъп до системата',
|
||||
'ldap_config_text' => 'Избраното местоположение ще бъде настроено за вички импортирани потребители. Това ще промени тяхното текущо местоположение, препоръчително е да оставите това поле празно.',
|
||||
|
||||
@@ -15,6 +15,7 @@ return [
|
||||
'user_deleted_warning' => 'Този потребител е изтрит. За да редактирате данните за него или да му зададете актив, трябва първо да възстановите потребителя.',
|
||||
'ldap_not_configured' => 'Интеграцията с LDAP не е конфигурирана за тази инсталация.',
|
||||
'password_resets_sent' => 'Избраните потребители, които са активирани и имат валиден е-майл адрес им беше изпратен линк за смяна на парола.',
|
||||
'not_activated' => 'This user cannot login, so they cannot accept assets via email.',
|
||||
'password_reset_sent' => 'Изпратена е връзка за въстановяване на паролата до :email!',
|
||||
'user_has_no_email' => 'Този потребител няма е-майл адрес в неговия профил.',
|
||||
'log_record_not_found' => 'Не е намерен лог запис за този потребител.',
|
||||
@@ -30,6 +31,7 @@ return [
|
||||
'unsuspend' => 'Потребителят активиран успешно.',
|
||||
'restored' => 'Потребителят е възстановен.',
|
||||
'import' => 'Потребителите заредени успешно.',
|
||||
'acceptance_reminder_sent' => 'Acceptance reminder sent for :count pending item.|Acceptance reminder sent for :count pending items.',
|
||||
],
|
||||
|
||||
'error' => [
|
||||
@@ -44,7 +46,7 @@ return [
|
||||
'delete_has_users_var' => 'Този потребител все още управлява друг потребител. Моля, първо изберете друг мениджър за този потребител.|Този потребител все още управлява :count потребители. Моля, първо изберете друг мениджър за тях.',
|
||||
'unsuspend' => 'Проблем при активирането на потребителя. Моля опитайте отново.',
|
||||
'import' => 'Проблем при зареждането на потребителите. Моля опитайте отново.',
|
||||
'asset_already_accepted' => 'Този актив е вече приет.',
|
||||
'asset_already_accepted' => 'This item has already been accepted.',
|
||||
'accept_or_decline' => 'Трябва да приемете или да откажете този актив.',
|
||||
'cannot_delete_yourself' => 'Ще се почувстваме много зле, ако се изтриете, моля, помислете отново.',
|
||||
'incorrect_user_accepted' => 'Активът, който се опитвате да приемете не е изписан към Вас.',
|
||||
@@ -54,6 +56,7 @@ return [
|
||||
'ldap_could_not_get_entries' => 'Проблем при извличането на резултат от LDAP сървъра. Моля прегледайте конфигурацията на LDAP.<br/>Грешка от LDAP сървъра:',
|
||||
'password_ldap' => 'Паролата за този профил се управлява от LDAP / Active Directory. Моля, свържете се с вашия ИТ отдел, за да промените паролата си.',
|
||||
'multi_company_items_assigned' => 'Този потребител претежава активи, които пренадлежат на друга фирма. Моля впишете ги обратно или редактирайте фирмата на активите.',
|
||||
'no_pending_acceptances' => 'This user has no pending acceptances to remind them about.',
|
||||
],
|
||||
|
||||
'deletefile' => [
|
||||
|
||||
@@ -54,7 +54,7 @@ return [
|
||||
'avatar_upload' => 'Качване на аватар',
|
||||
'back' => 'Назад',
|
||||
'bad_data' => 'Няма резултати.',
|
||||
'bulkaudit' => 'Групов одит',
|
||||
'bulkaudit' => 'Scanner Bulk Audit',
|
||||
'bulkaudit_status' => 'Статус на одита',
|
||||
'bulk_checkout' => 'Общо отписване',
|
||||
'bulk_edit' => 'Групово редактиране',
|
||||
@@ -122,7 +122,7 @@ return [
|
||||
'debug_warning_text' => 'Това приложение се изпълнява в режим на производство с разрешено отстраняване на грешки. Това може да изложи чувствителни данни, ако приложението ви е достъпно за външния свят. Забранете режим отстраняване на грешки чрез задаване на стойността <code>APP_DEBUF</code> <code>.env</code> във файла <code>false</code>.',
|
||||
'delete' => 'Изтриване',
|
||||
'delete_confirm' => 'Сигурни ли сте, че желаете изтриването на :item?',
|
||||
'delete_confirm_no_undo' => 'Сигурни ли сте че искате да изтриете :item? Това не може да бъде върнато на обратно.',
|
||||
'delete_confirm_no_undo' => 'Сигурни ли сте, че искате да изтриете :item? Това не може да бъде върнато на обратно.',
|
||||
'deleted' => 'Изтрито',
|
||||
'delete_seats' => 'Изтрити работни места за лиценз',
|
||||
'deletion_failed' => 'Неуспешно изтриване',
|
||||
@@ -154,7 +154,7 @@ return [
|
||||
'first_checkout' => '1<sup>ви</sup> изписване',
|
||||
'generate' => 'Генериране',
|
||||
'generate_labels' => 'Генериране на етикети',
|
||||
'github_markdown' => 'Това поле позволява въвеждането на <a href="https://help.github.com/articles/github-flavored-markdown/">Github вид markdown</a>.',
|
||||
'github_markdown' => 'This field accepts <a href="https://help.github.com/articles/github-flavored-markdown/" target="_blank">Github flavored markdown</a>.',
|
||||
'groups' => 'Групи',
|
||||
'gravatar_email' => 'Gravatar email адрес',
|
||||
'gravatar_url' => '<a href="http://gravatar.com"><small>Сменете си аватара на Gravatar.com</small></a>.',
|
||||
@@ -224,6 +224,9 @@ return [
|
||||
'next_audit_date_help' => 'Ако използвате одит във вашата организация, това обикновено се изчислява автоматично въз основа на последната дата на одит на актива' и честота на одит (в <code>Настройки на администратора > Сигнали</code>) и можете да оставите това празно. Можете ръчно да зададете тази дата тук, ако е необходимо, но тя трябва да е по-късна от последната дата на одит. ',
|
||||
'audit_images_help' => 'Можете да намерите изображения за одит в раздела за история на актива.',
|
||||
'no_email' => 'Няма е-майл адрес към този потребител',
|
||||
'no_value' => 'No value',
|
||||
'device_eol' => 'Device EOL',
|
||||
'na' => 'N/A',
|
||||
'last_audit' => 'Последният одит',
|
||||
'new' => 'new!',
|
||||
'no_depreciation' => 'Без амортизация',
|
||||
@@ -271,7 +274,7 @@ return [
|
||||
'rtd' => 'Готово за предоставяне',
|
||||
'requested_date' => 'Дата на заявката',
|
||||
'requested_assets' => 'Изискуеми активи',
|
||||
'requested_assets_menu' => 'Изискани артикули',
|
||||
'requested_assets_menu' => 'Изискуеми артикули',
|
||||
'request_canceled' => 'Заявка отменена',
|
||||
'request_item' => 'Поискайте този артикул',
|
||||
'external_link_tooltip' => 'Външна връзка към',
|
||||
@@ -559,6 +562,11 @@ return [
|
||||
'error_user_company_accept_view' => 'Актива заведен на вас пренадлежи към друга фирма, затова не можете да го приемете или откажете. Свържете се с вашият администратор',
|
||||
'error_assets_already_checked_out' => 'Един или повече от активите са вече изписани',
|
||||
'assigned_assets_removed' => 'Следните бяха премахнтати от избраните активи, защото са вече изписани',
|
||||
'upload_files' => 'Upload Files',
|
||||
'uploaded_files' => 'Uploaded Files',
|
||||
'sign_in_place' => 'Sign/Accept in place',
|
||||
'sign_in_place_help' => 'Check this box if you have the user present and wish for them to accept the item and sign/accept the EULA (when applicable) right now.',
|
||||
'unauthorized' => 'Unauthorized or unauthenticated.',
|
||||
'importer' => [
|
||||
'checked_out_to_fullname' => 'Изписан на: Full Name',
|
||||
'checked_out_to_first_name' => 'Изписан на: First Name',
|
||||
@@ -662,12 +670,16 @@ return [
|
||||
'child_locations' => 'Под локаций',
|
||||
'append' => 'Добави',
|
||||
'optional' => 'ПО ЖЕЛАНИЕ',
|
||||
'audit_by_field' => 'Audit by Field',
|
||||
'audit_by_field_help' => 'Auditing by scanning serial numbers is only an available option if serial numbers are required to be unique in the Admin Settings.',
|
||||
'audit_key' => 'Актив',
|
||||
|
||||
// Add form placeholders here
|
||||
'placeholders' => [
|
||||
'notes' => 'Добавете бележка',
|
||||
],
|
||||
|
||||
'last_note' => 'Last Note',
|
||||
'bulk_delete_associations' => [
|
||||
'general_assoc_warning' => ':item_name все още има свързани артикули. Моля премахнете ги преди да изтриете този :item.',
|
||||
'assoc_assets' => ':item_name е свързан към :asset_count артикула(и) и не може да бъде изтрит. Моля обновете вашите артикули, така че да не включват този :item и пробвайте отново.',
|
||||
@@ -691,26 +703,6 @@ return [
|
||||
'checkin_item' => 'Впиши :name',
|
||||
],
|
||||
|
||||
'skins' => [
|
||||
'site_default' => 'Настройки по подразбиране на сайта',
|
||||
'default_blue' => 'По подразбиране Синьо',
|
||||
'blue_dark' => 'Синьо (тъмен режим)',
|
||||
'green' => 'Зелено',
|
||||
'green_dark' => 'Зелено (тъмен режим)',
|
||||
'red' => 'Червено',
|
||||
'red_dark' => 'Червено (тъмен режим)',
|
||||
'orange' => 'Оранжево',
|
||||
'orange_dark' => 'Оранжево (тъмен режим)',
|
||||
'black' => 'Черно',
|
||||
'black_dark' => 'Черно (тъмен режим)',
|
||||
'purple' => 'Лилаво',
|
||||
'purple_dark' => 'Лилаво (тъмен режим)',
|
||||
'yellow' => 'Жълто',
|
||||
'yellow_dark' => 'Жълто (тъмен режим)',
|
||||
'high_contrast' => 'Висок контраст',
|
||||
|
||||
],
|
||||
|
||||
'select_all_none' => 'Маркирай всички',
|
||||
'generic_model_not_found' => ':model не беше намерен или вие нямате права да го достъпите',
|
||||
'report_not_editable' => 'Нямата права да редактирате този шаблон',
|
||||
@@ -754,4 +746,7 @@ return [
|
||||
|
||||
'months_plural' => '1 месец|:count месеца',
|
||||
|
||||
'token_unrevoked' => 'API token reinstated',
|
||||
'token_revoked' => 'API token revoked',
|
||||
|
||||
];
|
||||
|
||||
@@ -90,7 +90,7 @@ return [
|
||||
'password' => 'Парола',
|
||||
'password_reset' => 'Нулиране на паролата',
|
||||
'read_the_terms' => 'Моля прочетете условията по-долу.',
|
||||
'read_the_terms_and_click' => 'Моля прочетете условията за ползване по-долу и щракнете върху връзката в края, за да потвърдите че сте прочели и се съгласявате с условията на употреба и сте получили актива.',
|
||||
'read_the_terms_and_click' => 'Please read the terms of use below, and click on the link at the bottom to confirm that you read and agree to the terms of use, and have received the item.',
|
||||
'click_here_to_review_terms_and_accept_item' => 'Щракнете тук за да приемете условията за ползване и приемете артикула|Щракнете тук за да приемете условията за ползване и приемете артикулите',
|
||||
'requested' => 'Изискан',
|
||||
'reset_link' => 'Вашата връзка за повторно задаване на паролата',
|
||||
|
||||
@@ -107,8 +107,49 @@ return [
|
||||
],
|
||||
'accessoriesfiles' => [
|
||||
'name' => 'Управление на файловете на аксесоарите',
|
||||
'note' => 'Дава достъп за качване, сваляне и изтриване на файлове към аксесоарите.',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with accessories. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'assetsfiles' => [
|
||||
'name' => 'Manage Asset Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with assets. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'usersfiles' => [
|
||||
'name' => 'Manage User Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with users. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'modelsfiles' => [
|
||||
'name' => 'Manage Model Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with asset models on both the model view and the asset view screens. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'departmentsfiles' => [
|
||||
'name' => 'Manage Department Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with departments. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'suppliersfiles' => [
|
||||
'name' => 'Manage Supplier Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with suppliers. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'locationsfiles' => [
|
||||
'name' => 'Manage Location Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with locations.(This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'companiesfiles' => [
|
||||
'name' => 'Manage Company Files',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with companies. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'consumablesfiles' => [
|
||||
'name' => 'Управление на файловете на консумативите',
|
||||
'note' => 'Allows the user to upload, download, and delete files associated with consumables. (This only makes sense with view privileges or higher.)',
|
||||
],
|
||||
|
||||
'consumables' => [
|
||||
'name' => 'Консумативи',
|
||||
'note' => 'Дава достъп до раздел консумативи в програмата.',
|
||||
@@ -129,10 +170,7 @@ return [
|
||||
'name' => 'Изписва консумативи',
|
||||
'note' => 'Дава достъп за изписване на консумативи към потребители.',
|
||||
],
|
||||
'consumablesfiles' => [
|
||||
'name' => 'Управление на файловете на консумативите',
|
||||
'note' => 'Дава достъп за качване, сваляне и изтриване на файловете към консумативите.',
|
||||
],
|
||||
|
||||
'licenses' => [
|
||||
'name' => 'Лицензи',
|
||||
'note' => 'Дава достъп до раздел лицензи в програмата.',
|
||||
@@ -161,6 +199,11 @@ return [
|
||||
'name' => 'Управление на файловете на лицензите',
|
||||
'note' => 'Дава достъп за качване, сваляне и изтриване на файлове към лицензите.',
|
||||
],
|
||||
'componentsfiles' => [
|
||||
'name' => 'Управлява файловете за компоненти',
|
||||
'note' => 'Дава достъп за качване, сваляне и изтриване на файлове към компонентите.',
|
||||
],
|
||||
|
||||
'licenseskeys' => [
|
||||
'name' => 'Управление на лицензионни ключове',
|
||||
'note' => 'Дава достъп на потребителя да вижда лицензионни ключове към лицензите.',
|
||||
@@ -181,10 +224,7 @@ return [
|
||||
'componentsdelete' => [
|
||||
'name' => 'Изтрива компоненти',
|
||||
],
|
||||
'componentsfiles' => [
|
||||
'name' => 'Управлява файловете за компоненти',
|
||||
'note' => 'Дава достъп за качване, сваляне и изтриване на файлове към компонентите.',
|
||||
],
|
||||
|
||||
'componentscheckout' => [
|
||||
'name' => 'Изписване на компоненти',
|
||||
'note' => 'Дава достъп за изписване на компоненти към потребители.',
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user