Compare commits

...

3 Commits

Author SHA1 Message Date
snipe
b8b60b1d17 Additional tweaks for recursion
Signed-off-by: snipe <snipe@snipe.net>
2025-06-22 17:28:56 +01:00
snipe
7dbd8e99ba Moved dropdown list
Signed-off-by: snipe <snipe@snipe.net>
2025-06-18 16:04:38 +01:00
snipe
b5a8b29af5 Use show_in_list instead of activated
Signed-off-by: snipe <snipe@snipe.net>
2025-06-18 16:04:31 +01:00
8 changed files with 107 additions and 136 deletions

View File

@@ -336,6 +336,11 @@ class UsersController extends Controller
]
)->where('show_in_list', '=', '1');
if (($request->filled('subordinates')) && (!auth()->user()->isSuperUser())) {
// Regular manager sees only their subordinates + self
$users = auth()->user()->allSubordinates();
}
if ($request->filled('search')) {
$users = $users->where(function ($query) use ($request) {
$query->SimpleNameSearch($request->get('search'))

View File

@@ -47,62 +47,6 @@ class ViewAssetsController extends Controller
return array_unique($fieldArray);
}
/**
* Get list of users viewable by the current user.
*
* @param User $authUser
* @return \Illuminate\Support\Collection
*/
private function getViewableUsers(User $authUser): \Illuminate\Support\Collection
{
// SuperAdmin sees all users
if ($authUser->isSuperUser()) {
return User::select('id', 'first_name', 'last_name', 'username')
->where('activated', 1)
->orderBy('last_name')
->orderBy('first_name')
->get();
}
// Regular manager sees only their subordinates + self
$managedUsers = $authUser->getAllSubordinates();
// If user has subordinates, show them with self at beginning
if ($managedUsers->count() > 0) {
return collect([$authUser])->merge($managedUsers)
->sortBy('last_name')
->sortBy('first_name');
}
// User has no subordinates, only sees themselves
return collect([$authUser]);
}
/**
* Get the selected user ID from request or default to current user.
*
* @param Request $request
* @param \Illuminate\Support\Collection $subordinates
* @param int $defaultUserId
* @return int
*/
private function getSelectedUserId(Request $request, \Illuminate\Support\Collection $subordinates, int $defaultUserId): int
{
// If no subordinates or no user_id in request, return default
if ($subordinates->count() <= 1 || !$request->filled('user_id')) {
return $defaultUserId;
}
$requestedUserId = (int) $request->input('user_id');
// Validate if the requested user is allowed
if ($subordinates->contains('id', $requestedUserId)) {
return $requestedUserId;
}
// If invalid ID or not authorized, return default
return $defaultUserId;
}
/**
* Show user's assigned assets with optional manager view functionality.
@@ -110,18 +54,29 @@ class ViewAssetsController extends Controller
*/
public function getIndex(Request $request) : View | RedirectResponse
{
$authUser = auth()->user();
$settings = Setting::getSettings();
$subordinates = collect();
$selectedUserId = $authUser->id;
$subordinate_count = 0;
$viewingUser = auth()->user();
$userToView = auth()->user();
$userToViewId = auth()->id();
// Process manager view if enabled
if ($settings->manager_view_enabled) {
$subordinates = $this->getViewableUsers($authUser);
$selectedUserId = $this->getSelectedUserId($request, $subordinates, $authUser->id);
// Only do the (heavy) recursive subordinate count if the manager view is enabled AND
// the user is trying to view a different user than themselves.
if (($settings->manager_view_enabled == 1) || (request()->get('user_id') != auth()->id())) {
$subordinate_count = auth()->user()->allSubordinates()->count();
if (auth()->user()->allSubordinates()->find($userToViewId)) {
}
}
// Load the data for the user to be viewed (either auth user or selected subordinate)
\Log::error('Sub count: '.$subordinate_count);
\Log::error('$viewingUser '.$viewingUser);
\Log::error('$userToView '.$userToView);
\Log::error('$userToViewId '.$userToViewId);
\Log::error(print_r(auth()->user()->allSubordinates()->get(), true));
$userToView = User::with([
'assets',
'assets.model',
@@ -129,23 +84,21 @@ class ViewAssetsController extends Controller
'consumables',
'accessories',
'licenses'
])->find($selectedUserId);
])->find($userToViewId);
// If the user to view couldn't be found (shouldn't happen with proper logic), redirect with error
if (!$userToView) {
return redirect()->route('view-assets')->with('error', trans('admin/users/message.user_not_found'));
}
// Process custom fields for the user being viewed
$fieldArray = $this->extractCustomFields($userToView);
// Pass the necessary data to the view
return view('account/view-assets', [
'user' => $userToView, // Use 'user' for compatibility with the existing view
'field_array' => $fieldArray,
'settings' => $settings,
'subordinates' => $subordinates,
'selectedUserId' => $selectedUserId
'subordinates' => $subordinate_count > 0 ?? false,
'selectedUserId' => $userToViewId
]);
}

View File

@@ -971,10 +971,6 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
->orWhere('users.employee_num', 'LIKE', '%' . $search . '%')
->orWhere('users.username', 'LIKE', '%' . $search . '%')
->orwhereRaw('CONCAT(users.first_name," ",users.last_name) LIKE \''.$search.'%\'');
}
/**
@@ -1022,6 +1018,22 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
}
}
public function directReports()
{
return $this->hasMany(User::class, 'manager_id');
}
public function allSubordinates()
{
return $this->directReports()->with('allSubordinates');
}
/**
* Check if the current user is a direct or indirect manager of the given user.
*

View File

@@ -32369,7 +32369,8 @@ $(function () {
search: params.term,
page: params.page || 1,
assetStatusType: link.data("asset-status-type"),
companyId: link.data("company-id")
companyId: link.data("company-id"),
subordinates: link.data("subordinates")
};
return data;
},

View File

@@ -91302,7 +91302,8 @@ $(function () {
search: params.term,
page: params.page || 1,
assetStatusType: link.data("asset-status-type"),
companyId: link.data("company-id")
companyId: link.data("company-id"),
subordinates: link.data("subordinates")
};
return data;
},

View File

@@ -1,5 +1,5 @@
{
"/js/build/app.js": "/js/build/app.js?id=19253af36b58ed3fb6770c7bb944f079",
"/js/build/app.js": "/js/build/app.js?id=eeff00aa3bf3497d4ba36c3fd7ca0c20",
"/css/dist/skins/skin-black-dark.css": "/css/dist/skins/skin-black-dark.css?id=78bfb1c7b5782df4fb0ac7e36f80f847",
"/css/dist/skins/_all-skins.css": "/css/dist/skins/_all-skins.css?id=503d0b09e157a22f555e3670d1ec9bb5",
"/css/build/overrides.css": "/css/build/overrides.css?id=2bfc7b71d951c5ac026dbc034f7373b1",
@@ -111,5 +111,5 @@
"/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=54d676a6ea8677dd48f6c4b3041292cf",
"/js/build/vendor.js": "/js/build/vendor.js?id=89dffa552c6e3abe3a2aac6c9c7b466b",
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=60097b6b56d80cbc76257d4ecf6f57b4",
"/js/dist/all.js": "/js/dist/all.js?id=8c6d7286f667eeb62a0a28a09851a6c3"
"/js/dist/all.js": "/js/dist/all.js?id=fe4be0933b6c05df1d795f53da658dc7"
}

View File

@@ -199,7 +199,10 @@ $(function () {
page: params.page || 1,
assetStatusType: link.data("asset-status-type"),
companyId: link.data("company-id"),
subordinates: link.data("subordinates"),
};
return data;
},
/* processResults: function (data, params) {

View File

@@ -6,6 +6,25 @@
@parent
@stop
@section('header_right')
{{-- Manager View Dropdown --}}
@if (isset($settings) && ($settings->manager_view_enabled==1) && ($subordinates))
<form method="GET" action="{{ route('view-assets') }}" class="pull-right" role="form">
<div class="form-group" style="margin-bottom: 0;">
<label for="user_id" class="control-label" style="margin-right: 10px;">
{{ trans('general.select_user') }}:
</label>
<select class="js-data-ajax form-control select2" data-endpoint="users" data-subordinates="true" data-placeholder="{{ trans('general.select_user') }}" name="user_id" style="width: 450px" id="user_id" aria-label="user_id" onchange="this.form.submit()">
</select>
</div>
</form>
@endif
@stop
{{-- Account page content --}}
@section('content')
@@ -25,30 +44,7 @@
</div>
@endif
{{-- Manager View Dropdown --}}
@if (isset($settings) && $settings->manager_view_enabled && isset($subordinates) && $subordinates->count() > 1)
<div class="row hidden-print" style="margin-bottom: 15px;">
<div class="col-md-12">
<form method="GET" action="{{ route('view-assets') }}" class="pull-right" role="form">
<div class="form-group" style="margin-bottom: 0;">
<label for="user_id" class="control-label" style="margin-right: 10px;">
{{ trans('general.view_user_assets') }}:
</label>
<select name="user_id" id="user_id" class="form-control select2" onchange="this.form.submit()" style="width: 250px; display: inline-block;">
@foreach ($subordinates as $subordinate)
<option value="{{ $subordinate->id }}" {{ (int)$selectedUserId === (int)$subordinate->id ? ' selected' : '' }}>
{{ $subordinate->present()->fullName() }}
@if ($subordinate->id == auth()->id())
({{ trans('general.me') }})
@endif
</option>
@endforeach
</select>
</div>
</form>
</div>
</div>
@endif
<div class="row">
<div class="col-md-12">
@@ -135,6 +131,7 @@
<div class="col-md-12 text-center">
<img src="{{ $user->present()->gravatar() }}" class="img-thumbnail hidden-print" style="margin-bottom: 20px;" alt="{{ $user->present()->fullName() }}" alt="User avatar">
</div>
@if ((isset($selectedUserId)) && ($selectedUserId == auth()->id()))
@can('self.profile')
<div class="col-md-12">
<a href="{{ route('profile') }}" style="width: 100%;" class="btn btn-sm btn-warning btn-social btn-block hidden-print">
@@ -161,16 +158,15 @@
</a>
</div>
@endcan
@endif
@if ($user->allAssignedCount() > 0)
<div class="col-md-12" style="padding-top: 5px;">
<a href="{{ route('profile.print') }}" style="width: 100%;" class="btn btn-sm btn-primary btn-social btn-block hidden-print" target="_blank" rel="noopener">
<x-icon type="print" class="fa-fw" />
{{ trans('admin/users/general.print_assigned') }}
</a>
</div>
<div class="col-md-12" style="padding-top: 5px;">
@if (!empty($user->email))
<form action="{{ route('profile.email_assets') }}" method="POST">
@@ -187,8 +183,8 @@
</button>
@endif
</div>
@endif
<br><br>
</div>
<!-- End button column -->