Merge remote-tracking branch 'origin/develop'
Some checks failed
CodeQL Security Scan / CodeQL Security Scan (javascript) (push) Has been cancelled
Codacy Security Scan / Codacy Security Scan (push) Has been cancelled
Docker images (Alpine) / docker (push) Has been cancelled
Docker images / docker (push) Has been cancelled
Tests in MySQL / PHP ${{ matrix.php-version }} (8.1) (push) Has been cancelled
Tests in MySQL / PHP ${{ matrix.php-version }} (8.2) (push) Has been cancelled
Tests in MySQL / PHP ${{ matrix.php-version }} (8.3) (push) Has been cancelled
Tests in SQLite / PHP ${{ matrix.php-version }} (8.1.1) (push) Has been cancelled

This commit is contained in:
snipe 2024-09-25 20:45:02 +01:00
commit 6c85ba3495
6 changed files with 189 additions and 114 deletions

View file

@ -13,6 +13,7 @@ use App\Models\Group;
use App\Models\LicenseSeat; use App\Models\LicenseSeat;
use App\Models\ConsumableAssignment; use App\Models\ConsumableAssignment;
use App\Models\Consumable; use App\Models\Consumable;
use App\Models\Setting;
use App\Models\User; use App\Models\User;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Http\Request; use Illuminate\Http\Request;
@ -35,7 +36,7 @@ class BulkUsersController extends Controller
*/ */
public function edit(Request $request) public function edit(Request $request)
{ {
$this->authorize('update', User::class); $this->authorize('view', User::class);
// Make sure there were users selected // Make sure there were users selected
if (($request->filled('ids')) && (count($request->input('ids')) > 0)) { if (($request->filled('ids')) && (count($request->input('ids')) > 0)) {
@ -47,16 +48,18 @@ class BulkUsersController extends Controller
// bulk edit, display the bulk edit form // bulk edit, display the bulk edit form
if ($request->input('bulk_actions') == 'edit') { if ($request->input('bulk_actions') == 'edit') {
$this->authorize('update', User::class);
return view('users/bulk-edit', compact('users')) return view('users/bulk-edit', compact('users'))
->with('groups', Group::pluck('name', 'id')); ->with('groups', Group::pluck('name', 'id'));
// bulk delete, display the bulk delete confirmation form // bulk delete, display the bulk delete confirmation form
} elseif ($request->input('bulk_actions') == 'delete') { } elseif ($request->input('bulk_actions') == 'delete') {
$this->authorize('delete', User::class);
return view('users/confirm-bulk-delete')->with('users', $users)->with('statuslabel_list', Helper::statusLabelList()); return view('users/confirm-bulk-delete')->with('users', $users)->with('statuslabel_list', Helper::statusLabelList());
// merge, confirm they have at least 2 users selected and display the merge screen // merge, confirm they have at least 2 users selected and display the merge screen
} elseif ($request->input('bulk_actions') == 'merge') { } elseif ($request->input('bulk_actions') == 'merge') {
$this->authorize('delete', User::class);
if (($request->filled('ids')) && (count($request->input('ids')) > 1)) { if (($request->filled('ids')) && (count($request->input('ids')) > 1)) {
return view('users/confirm-merge')->with('users', $users); return view('users/confirm-merge')->with('users', $users);
// Not enough users selected, send them back // Not enough users selected, send them back
@ -76,6 +79,33 @@ class BulkUsersController extends Controller
} }
return redirect()->back()->with('success', trans('admin/users/message.password_resets_sent')); return redirect()->back()->with('success', trans('admin/users/message.password_resets_sent'));
} elseif ($request->input('bulk_actions') == 'print') {
$users = User::query()
->with([
'assets.assetlog',
'assets.assignedAssets.assetlog',
'assets.assignedAssets.defaultLoc',
'assets.assignedAssets.location',
'assets.assignedAssets.model.category',
'assets.defaultLoc',
'assets.location',
'assets.model.category',
'accessories.assetlog',
'accessories.category',
'accessories.manufacturer',
'consumables.assetlog',
'consumables.category',
'consumables.manufacturer',
'licenses.category',
])
->withTrashed()
->findMany($request->input('ids'));
$users->each(fn($user) => $this->authorize('view', $user));
return view('users.print')
->with('users', $users)
->with('settings', Setting::getSettings());
} }
} }

View file

@ -597,23 +597,37 @@ class UsersController extends Controller
public function printInventory($id) public function printInventory($id)
{ {
$this->authorize('view', User::class); $this->authorize('view', User::class);
if ($user = User::where('id', $id)->withTrashed()->first()) {
$user = User::where('id', $id)
->with([
'assets.assetlog',
'assets.assignedAssets.assetlog',
'assets.assignedAssets.defaultLoc',
'assets.assignedAssets.location',
'assets.assignedAssets.model.category',
'assets.defaultLoc',
'assets.location',
'assets.model.category',
'accessories.assetlog',
'accessories.category',
'accessories.manufacturer',
'consumables.assetlog',
'consumables.category',
'consumables.manufacturer',
'licenses.category',
])
->withTrashed()
->first();
if ($user) {
$this->authorize('view', $user); $this->authorize('view', $user);
$assets = Asset::where('assigned_to', $id)->where('assigned_type', User::class)->with('model', 'model.category')->get();
$accessories = $user->accessories()->get();
$consumables = $user->consumables()->get();
return view('users/print')->with('assets', $assets) return view('users.print')
->with('licenses', $user->licenses()->get()) ->with('users', [$user])
->with('accessories', $accessories)
->with('consumables', $consumables)
->with('show_user', $user)
->with('settings', Setting::getSettings()); ->with('settings', Setting::getSettings());
} }
return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found', compact('id'))); return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found', compact('id')));
} }
/** /**

View file

@ -282,6 +282,7 @@ return [
'status_label' => 'Status Label', 'status_label' => 'Status Label',
'status' => 'Status', 'status' => 'Status',
'accept_eula' => 'Acceptance Agreement', 'accept_eula' => 'Acceptance Agreement',
'show_or_hide_eulas' => 'Show/Hide EULAs',
'supplier' => 'Supplier', 'supplier' => 'Supplier',
'suppliers' => 'Suppliers', 'suppliers' => 'Suppliers',
'sure_to_delete' => 'Are you sure you wish to delete', 'sure_to_delete' => 'Are you sure you wish to delete',

View file

@ -1,3 +1,4 @@
@can('view', \App\Models\User::class)
<div id="userBulkEditToolbar"> <div id="userBulkEditToolbar">
{{ Form::open([ {{ Form::open([
'method' => 'POST', 'method' => 'POST',
@ -6,18 +7,25 @@
'id' => 'usersBulkForm']) }} 'id' => 'usersBulkForm']) }}
@if (request('status')!='deleted') @if (request('status')!='deleted')
@can('delete', \App\Models\User::class)
<div id="users-toolbar"> <div id="users-toolbar">
<label for="bulk_actions" class="sr-only">{{ trans('general.bulk_actions') }}</label> <label for="bulk_actions" class="sr-only">{{ trans('general.bulk_actions') }}</label>
<select name="bulk_actions" class="form-control select2" style="min-width:300px;" aria-label="bulk_actions"> <select name="bulk_actions" class="form-control select2" style="min-width:300px;" aria-label="bulk_actions">
@can('update', \App\Models\User::class)
<option value="edit">{{ trans('general.bulk_edit') }}</option> <option value="edit">{{ trans('general.bulk_edit') }}</option>
@endcan
@can('delete', \App\Models\User::class)
<option value="delete">{!! trans('general.bulk_checkin_delete') !!}</option> <option value="delete">{!! trans('general.bulk_checkin_delete') !!}</option>
<option value="merge">{!! trans('general.merge_users') !!}</option> <option value="merge">{!! trans('general.merge_users') !!}</option>
@endcan
<option value="bulkpasswordreset">{{ trans('button.send_password_link') }}</option> <option value="bulkpasswordreset">{{ trans('button.send_password_link') }}</option>
<option value="print">{{ trans('admin/users/general.print_assigned') }}</option>
</select> </select>
<button class="btn btn-primary" id="bulkUserEditButton" disabled>{{ trans('button.go') }}</button> <button class="btn btn-primary" id="bulkUserEditButton" disabled>{{ trans('button.go') }}</button>
</div> </div>
@endcan
@endif @endif
{{ Form::close() }} {{ Form::close() }}
</div> </div>
@endcan

View file

@ -2,7 +2,11 @@
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>{{ trans('general.assigned_to', ['name' => $show_user->present()->fullName()]) }} - {{ date('Y-m-d H:i', time()) }}</title> @if (count($users) === 1)
<title>{{ trans('general.assigned_to', ['name' => $users[0]->present()->fullName()]) }} - {{ date('Y-m-d H:i', time()) }}</title>
@else
<title>{{ trans('admin/users/general.print_assigned') }} - {{ date('Y-m-d H:i', time()) }}</title>
@endisset
<link rel="shortcut icon" type="image/ico" href="{{ ($snipeSettings) && ($snipeSettings->favicon!='') ? Storage::disk('public')->url(e($snipeSettings->favicon)) : config('app.url').'/favicon.ico' }}"> <link rel="shortcut icon" type="image/ico" href="{{ ($snipeSettings) && ($snipeSettings->favicon!='') ? Storage::disk('public')->url(e($snipeSettings->favicon)) : config('app.url').'/favicon.ico' }}">
@ -33,6 +37,10 @@
size: A4; size: A4;
} }
#start_of_user_section {
break-before: page;
}
.print-logo { .print-logo {
max-height: 40px; max-height: 40px;
} }
@ -54,6 +62,16 @@
</head> </head>
<body> <body>
{{-- If we are rendering multiple users we'll add the ability to show/hide EULAs for all of them at once via this button --}}
@if (count($users) > 1)
<div class="pull-right hidden-print">
<span>{{ trans('general.show_or_hide_eulas') }}</span>
<button class="btn btn-default" type="button" data-toggle="collapse" data-target=".eula-row" aria-expanded="false" aria-controls="eula-row" title="EULAs">
<i class="fa fa-eye-slash"></i>
</button>
</div>
@endif
@if ($snipeSettings->logo_print_assets=='1') @if ($snipeSettings->logo_print_assets=='1')
@if ($snipeSettings->brand == '3') @if ($snipeSettings->brand == '3')
@ -72,6 +90,8 @@
@endif @endif
@endif @endif
@foreach ($users as $show_user)
<div id="start_of_user_section"> {{-- used for page breaks when printing --}}</div>
<h3> <h3>
{{ trans('general.assigned_to', ['name' => $show_user->present()->fullName()]) }} {{ trans('general.assigned_to', ['name' => $show_user->present()->fullName()]) }}
{{ ($show_user->employee_num!='') ? ' (#'.$show_user->employee_num.') ' : '' }} {{ ($show_user->employee_num!='') ? ' (#'.$show_user->employee_num.') ' : '' }}
@ -79,15 +99,13 @@
</h3> </h3>
<p></p>{{ trans('admin/users/general.all_assigned_list_generation')}} {{ Helper::getFormattedDateObject(now(), 'datetime', false) }} <p></p>{{ trans('admin/users/general.all_assigned_list_generation')}} {{ Helper::getFormattedDateObject(now(), 'datetime', false) }}
</body> @if ($show_user->assets->count() > 0)
@if ($assets->count() > 0)
@php @php
$counter = 1; $counter = 1;
@endphp @endphp
<div id="assets-toolbar"> <div id="assets-toolbar">
<h4>{{ trans_choice('general.countable.assets', $assets->count(), ['count' => $assets->count()]) }} <h4>{{ trans_choice('general.countable.assets', $show_user->assets->count(), ['count' => $show_user->assets->count()]) }}
</h4> </h4>
</div> </div>
@ -119,7 +137,7 @@
<th data-field="signature" data-sortable="true" data-visible="true">{{ trans('general.signature') }}</th> <th data-field="signature" data-sortable="true" data-visible="true">{{ trans('general.signature') }}</th>
</thead> </thead>
<tbody> <tbody>
@foreach ($assets as $asset) @foreach ($show_user->assets as $asset)
@php @php
if ($asset->model->category->getEula()) $eulas[] = $asset->model->category->getEula() if ($asset->model->category->getEula()) $eulas[] = $asset->model->category->getEula()
@endphp @endphp
@ -185,9 +203,9 @@
</table> </table>
@endif @endif
@if ($licenses->count() > 0) @if ($show_user->licenses->count() > 0)
<div id="licenses-toolbar"> <div id="licenses-toolbar">
<h4>{{ trans_choice('general.countable.licenses', $licenses->count(), ['count' => $licenses->count()]) }}</h4> <h4>{{ trans_choice('general.countable.licenses', $show_user->licenses->count(), ['count' => $show_user->licenses->count()]) }}</h4>
</div> </div>
<table <table
@ -216,7 +234,7 @@
$lcounter = 1; $lcounter = 1;
@endphp @endphp
@foreach ($licenses as $license) @foreach ($show_user->licenses as $license)
@php @php
if ($license->category->getEula()) $eulas[] = $license->category->getEula() if ($license->category->getEula()) $eulas[] = $license->category->getEula()
@endphp @endphp
@ -240,9 +258,9 @@
@endif @endif
@if ($accessories->count() > 0) @if ($show_user->accessories->count() > 0)
<div id="accessories-toolbar"> <div id="accessories-toolbar">
<h4>{{ trans_choice('general.countable.accessories', $accessories->count(), ['count' => $accessories->count()]) }}</h4> <h4>{{ trans_choice('general.countable.accessories', $show_user->accessories->count(), ['count' => $show_user->accessories->count()]) }}</h4>
</div> </div>
<table <table
@ -273,7 +291,7 @@
$acounter = 1; $acounter = 1;
@endphp @endphp
@foreach ($accessories as $accessory) @foreach ($show_user->accessories as $accessory)
@if ($accessory) @if ($accessory)
@php @php
if ($accessory->category->getEula()) $eulas[] = $accessory->category->getEula() if ($accessory->category->getEula()) $eulas[] = $accessory->category->getEula()
@ -303,9 +321,9 @@
</table> </table>
@endif @endif
@if ($consumables->count() > 0) @if ($show_user->consumables->count() > 0)
<div id="consumables-toolbar"> <div id="consumables-toolbar">
<h4>{{ trans_choice('general.countable.consumables', $consumables->count(), ['count' => $consumables->count()]) }}</h4> <h4>{{ trans_choice('general.countable.consumables', $show_user->consumables->count(), ['count' => $show_user->consumables->count()]) }}</h4>
</div> </div>
<table <table
@ -336,7 +354,7 @@
$ccounter = 1; $ccounter = 1;
@endphp @endphp
@foreach ($consumables as $consumable) @foreach ($show_user->consumables as $consumable)
@if ($consumable) @if ($consumable)
@php @php
if ($consumable->category->getEula()) $eulas[] = $consumable->category->getEula() if ($consumable->category->getEula()) $eulas[] = $consumable->category->getEula()
@ -366,15 +384,18 @@
</table> </table>
@endif @endif
{{-- This may have been render at the top of the page if we're rendering more than one user... --}}
@if (count($users) === 1)
<p></p> <p></p>
<div class="pull-right"> <div class="pull-right">
<button class="btn btn-default hidden-print" type="button" data-toggle="collapse" data-target="#eula-row" aria-expanded="false" aria-controls="eula-row" title="EULAs"> <button class="btn btn-default hidden-print" type="button" data-toggle="collapse" data-target=".eula-row" aria-expanded="false" aria-controls="eula-row" title="EULAs">
<i class="fa fa-eye-slash"></i> <i class="fa fa-eye-slash"></i>
</button> </button>
</div> </div>
@endif
<table style="margin-top: 80px;" class="snipe-table"> <table style="margin-top: 80px;">
<tr class="collapse" id="eula-row"> <tr class="collapse eula-row">
<td style="padding-right: 10px; vertical-align: top; font-weight: bold;">EULA</td> <td style="padding-right: 10px; vertical-align: top; font-weight: bold;">EULA</td>
<td style="padding-right: 10px; vertical-align: top; padding-bottom: 80px;" colspan="3"> <td style="padding-right: 10px; vertical-align: top; padding-bottom: 80px;" colspan="3">
@php @php
@ -414,6 +435,7 @@
</tr> </tr>
</table> </table>
@endforeach
{{-- Javascript files --}} {{-- Javascript files --}}
<script src="{{ url(mix('js/dist/all.js')) }}" nonce="{{ csrf_token() }}"></script> <script src="{{ url(mix('js/dist/all.js')) }}" nonce="{{ csrf_token() }}"></script>