From ff145abbe720f36604585005b26cf62873169f56 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Mon, 12 Aug 2024 16:13:03 -0500 Subject: [PATCH 01/17] use array for eager loading, makes ide prettier --- app/Http/Controllers/Users/UsersController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Users/UsersController.php b/app/Http/Controllers/Users/UsersController.php index 1e203e71d5..bad16458d6 100755 --- a/app/Http/Controllers/Users/UsersController.php +++ b/app/Http/Controllers/Users/UsersController.php @@ -232,7 +232,7 @@ class UsersController extends Controller $permissions = $request->input('permissions', []); app('request')->request->set('permissions', $permissions); - $user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($id); + $user = User::with(['assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc'])->withTrashed()->find($id); // User is valid - continue... if ($user) { @@ -263,7 +263,7 @@ class UsersController extends Controller $user->activated = $request->input('activated', 0); $user->jobtitle = $request->input('jobtitle', null); $user->phone = $request->input('phone'); - $user->location_id = $request->input('location_id', null); + $user->location_id = $request->input('location_id', null); //here $user->company_id = Company::getIdForUser($request->input('company_id', null)); $user->manager_id = $request->input('manager_id', null); $user->notes = $request->input('notes'); From cc3b8e0681f74276958c988d986de07cff3e798d Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Mon, 12 Aug 2024 16:58:21 -0500 Subject: [PATCH 02/17] this should more or less work, but i need to determine if this is the best way --- app/Http/Controllers/Users/UsersController.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Users/UsersController.php b/app/Http/Controllers/Users/UsersController.php index bad16458d6..96fbae49af 100755 --- a/app/Http/Controllers/Users/UsersController.php +++ b/app/Http/Controllers/Users/UsersController.php @@ -263,7 +263,16 @@ class UsersController extends Controller $user->activated = $request->input('activated', 0); $user->jobtitle = $request->input('jobtitle', null); $user->phone = $request->input('phone'); - $user->location_id = $request->input('location_id', null); //here + $user->location_id = $request->input('location_id', null); + if ($request->has('company_id')) { + if ($user->assets->count() > 0) { + if ($user->assets()->pluck('company_id') != $user->getRawOriginal('company_id')) { + { + return back()->with('error', 'this user has assets, check them in first'); + } + } + } + } $user->company_id = Company::getIdForUser($request->input('company_id', null)); $user->manager_id = $request->input('manager_id', null); $user->notes = $request->input('notes'); From ec863df0074ce785aa3ac80f4871accb8eb2145b Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Mon, 12 Aug 2024 16:58:53 -0500 Subject: [PATCH 03/17] rm conditional that might be unnecessary --- app/Http/Controllers/Users/UsersController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Users/UsersController.php b/app/Http/Controllers/Users/UsersController.php index 96fbae49af..adf2d5f3dd 100755 --- a/app/Http/Controllers/Users/UsersController.php +++ b/app/Http/Controllers/Users/UsersController.php @@ -266,11 +266,11 @@ class UsersController extends Controller $user->location_id = $request->input('location_id', null); if ($request->has('company_id')) { if ($user->assets->count() > 0) { - if ($user->assets()->pluck('company_id') != $user->getRawOriginal('company_id')) { + //if ($user->assets()->pluck('company_id') != $user->getRawOriginal('company_id')) { { return back()->with('error', 'this user has assets, check them in first'); } - } + //} } } $user->company_id = Company::getIdForUser($request->input('company_id', null)); From 09f2739298933ea8150a6dfda4aa19b3c5baa94f Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Tue, 13 Aug 2024 13:45:41 -0500 Subject: [PATCH 04/17] works, un-reassignable licenses are an issue --- app/Http/Controllers/Users/UsersController.php | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/app/Http/Controllers/Users/UsersController.php b/app/Http/Controllers/Users/UsersController.php index adf2d5f3dd..9ff0152484 100755 --- a/app/Http/Controllers/Users/UsersController.php +++ b/app/Http/Controllers/Users/UsersController.php @@ -186,7 +186,7 @@ class UsersController extends Controller { $this->authorize('update', User::class); - $user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($id); + $user = User::with(['assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc'])->withTrashed()->find($id); if ($user) { @@ -235,9 +235,15 @@ class UsersController extends Controller $user = User::with(['assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc'])->withTrashed()->find($id); // User is valid - continue... + + if ($user) { $this->authorize('update', $user); + if ($request->has('company_id') && $user->allAssignedCount() > 0 && Setting::getSettings()->full_multiple_companies_support) { + return back()->with('error', 'this user has assets, check them in first'); + } + // Figure out of this user was an admin before this edit $orig_permissions_array = $user->decodePermissions(); $orig_superuser = '0'; @@ -264,15 +270,7 @@ class UsersController extends Controller $user->jobtitle = $request->input('jobtitle', null); $user->phone = $request->input('phone'); $user->location_id = $request->input('location_id', null); - if ($request->has('company_id')) { - if ($user->assets->count() > 0) { - //if ($user->assets()->pluck('company_id') != $user->getRawOriginal('company_id')) { - { - return back()->with('error', 'this user has assets, check them in first'); - } - //} - } - } + $user->company_id = Company::getIdForUser($request->input('company_id', null)); $user->manager_id = $request->input('manager_id', null); $user->notes = $request->input('notes'); From 120cfd13c544fb79e69f5f59aa44f908b4a39947 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Tue, 13 Aug 2024 14:07:40 -0500 Subject: [PATCH 05/17] translation --- app/Http/Controllers/Users/UsersController.php | 2 +- resources/lang/en-US/admin/users/message.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Users/UsersController.php b/app/Http/Controllers/Users/UsersController.php index 9ff0152484..631ab3bc31 100755 --- a/app/Http/Controllers/Users/UsersController.php +++ b/app/Http/Controllers/Users/UsersController.php @@ -241,7 +241,7 @@ class UsersController extends Controller $this->authorize('update', $user); if ($request->has('company_id') && $user->allAssignedCount() > 0 && Setting::getSettings()->full_multiple_companies_support) { - return back()->with('error', 'this user has assets, check them in first'); + return back()->with('error', trans('admin/users/message.multi_company_items_assigned')); } // Figure out of this user was an admin before this edit diff --git a/resources/lang/en-US/admin/users/message.php b/resources/lang/en-US/admin/users/message.php index 4d014775bd..0f41d463e1 100644 --- a/resources/lang/en-US/admin/users/message.php +++ b/resources/lang/en-US/admin/users/message.php @@ -53,6 +53,7 @@ return array( 'ldap_could_not_search' => 'Could not search the LDAP server. Please check your LDAP server configuration in the LDAP config file.
Error from LDAP Server:', 'ldap_could_not_get_entries' => 'Could not get entries from the LDAP server. Please check your LDAP server configuration in the LDAP config file.
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, please check them in before moving companies.' ), 'deletefile' => array( From 20ec420ba3a51638f7934e5a3820907760fc544c Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Wed, 14 Aug 2024 13:53:29 -0500 Subject: [PATCH 06/17] not quite done, api side needs some work --- app/Http/Controllers/Api/UsersController.php | 2 +- .../Controllers/Users/UsersController.php | 122 ++++++++---------- app/Http/Requests/SaveUserRequest.php | 10 ++ routes/web/users.php | 5 +- 4 files changed, 70 insertions(+), 69 deletions(-) diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php index 9200f80b1d..ae6968a475 100644 --- a/app/Http/Controllers/Api/UsersController.php +++ b/app/Http/Controllers/Api/UsersController.php @@ -427,7 +427,7 @@ class UsersController extends Controller * @param \Illuminate\Http\Request $request * @param int $id */ - public function update(SaveUserRequest $request, $id) : JsonResponse + public function update(SaveUserRequest $request, User $user): JsonResponse { $this->authorize('update', User::class); diff --git a/app/Http/Controllers/Users/UsersController.php b/app/Http/Controllers/Users/UsersController.php index 631ab3bc31..e609727c00 100755 --- a/app/Http/Controllers/Users/UsersController.php +++ b/app/Http/Controllers/Users/UsersController.php @@ -214,90 +214,84 @@ class UsersController extends Controller * @return \Illuminate\Http\RedirectResponse * @throws \Illuminate\Auth\Access\AuthorizationException */ - public function update(SaveUserRequest $request, $id = null) + public function update(SaveUserRequest $request, User $user) { $this->authorize('update', User::class); // This is a janky hack to prevent people from changing admin demo user data on the public demo. // The $ids 1 and 2 are special since they are seeded as superadmins in the demo seeder. // Thanks, jerks. You are why we can't have nice things. - snipe - - if ((($id == 1) || ($id == 2)) && (config('app.lock_passwords'))) { + if ((($user->id == 1) || ($user->id == 2)) && (config('app.lock_passwords'))) { return redirect()->route('users.index')->with('error', trans('general.permission_denied_superuser_demo')); } - // We need to reverse the UI specific logic for our // permissions here before we update the user. $permissions = $request->input('permissions', []); app('request')->request->set('permissions', $permissions); - $user = User::with(['assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc'])->withTrashed()->find($id); + $user->load(['assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc'])->withTrashed(); - // User is valid - continue... + $this->authorize('update', $user); - - if ($user) { - $this->authorize('update', $user); - - if ($request->has('company_id') && $user->allAssignedCount() > 0 && Setting::getSettings()->full_multiple_companies_support) { - return back()->with('error', trans('admin/users/message.multi_company_items_assigned')); - } + //see if i can get this working at request level + //if ($request->has('company_id') && $user->allAssignedCount() > 0 && Setting::getSettings()->full_multiple_companies_support) { + // return back()->with('error', trans('admin/users/message.multi_company_items_assigned')); + //} // Figure out of this user was an admin before this edit - $orig_permissions_array = $user->decodePermissions(); - $orig_superuser = '0'; - if (is_array($orig_permissions_array)) { - if (array_key_exists('superuser', $orig_permissions_array)) { - $orig_superuser = $orig_permissions_array['superuser']; - } + $orig_permissions_array = $user->decodePermissions(); + $orig_superuser = '0'; + if (is_array($orig_permissions_array)) { + if (array_key_exists('superuser', $orig_permissions_array)) { + $orig_superuser = $orig_permissions_array['superuser']; } + } - // Only save groups if the user is a superuser - if (auth()->user()->isSuperUser()) { - $user->groups()->sync($request->input('groups')); - } + // Only save groups if the user is a superuser + if (auth()->user()->isSuperUser()) { + $user->groups()->sync($request->input('groups')); + } - // Update the user fields - $user->username = trim($request->input('username')); - $user->email = trim($request->input('email')); - $user->first_name = $request->input('first_name'); - $user->last_name = $request->input('last_name'); - $user->two_factor_optin = $request->input('two_factor_optin') ?: 0; - $user->locale = $request->input('locale'); - $user->employee_num = $request->input('employee_num'); - $user->activated = $request->input('activated', 0); - $user->jobtitle = $request->input('jobtitle', null); - $user->phone = $request->input('phone'); - $user->location_id = $request->input('location_id', null); + // Update the user fields + $user->username = trim($request->input('username')); + $user->email = trim($request->input('email')); + $user->first_name = $request->input('first_name'); + $user->last_name = $request->input('last_name'); + $user->two_factor_optin = $request->input('two_factor_optin') ?: 0; + $user->locale = $request->input('locale'); + $user->employee_num = $request->input('employee_num'); + $user->activated = $request->input('activated', 0); + $user->jobtitle = $request->input('jobtitle', null); + $user->phone = $request->input('phone'); + $user->location_id = $request->input('location_id', null); + $user->company_id = Company::getIdForUser($request->input('company_id', null)); + $user->manager_id = $request->input('manager_id', null); + $user->notes = $request->input('notes'); + $user->department_id = $request->input('department_id', null); + $user->address = $request->input('address', null); + $user->city = $request->input('city', null); + $user->state = $request->input('state', null); + $user->country = $request->input('country', null); + // if a user is editing themselves we should always keep activated true + $user->activated = $request->input('activated', $request->user()->is($user) ? 1 : 0); + $user->zip = $request->input('zip', null); + $user->remote = $request->input('remote', 0); + $user->vip = $request->input('vip', 0); + $user->website = $request->input('website', null); + $user->start_date = $request->input('start_date', null); + $user->end_date = $request->input('end_date', null); + $user->autoassign_licenses = $request->input('autoassign_licenses', 0); - $user->company_id = Company::getIdForUser($request->input('company_id', null)); - $user->manager_id = $request->input('manager_id', null); - $user->notes = $request->input('notes'); - $user->department_id = $request->input('department_id', null); - $user->address = $request->input('address', null); - $user->city = $request->input('city', null); - $user->state = $request->input('state', null); - $user->country = $request->input('country', null); - // if a user is editing themselves we should always keep activated true - $user->activated = $request->input('activated', $request->user()->is($user) ? 1 : 0); - $user->zip = $request->input('zip', null); - $user->remote = $request->input('remote', 0); - $user->vip = $request->input('vip', 0); - $user->website = $request->input('website', null); - $user->start_date = $request->input('start_date', null); - $user->end_date = $request->input('end_date', null); - $user->autoassign_licenses = $request->input('autoassign_licenses', 0); + // Update the location of any assets checked out to this user + Asset::where('assigned_type', User::class) + ->where('assigned_to', $user->id) + ->update(['location_id' => $request->input('location_id', null)]); - // Update the location of any assets checked out to this user - Asset::where('assigned_type', User::class) - ->where('assigned_to', $user->id) - ->update(['location_id' => $request->input('location_id', null)]); - - // Do we want to update the user password? - if ($request->filled('password')) { - $user->password = bcrypt($request->input('password')); - } + // Do we want to update the user password? + if ($request->filled('password')) { + $user->password = bcrypt($request->input('password')); + } // Update the location of any assets checked out to this user @@ -325,13 +319,7 @@ class UsersController extends Controller return redirect()->to(Helper::getRedirectOption($request, $user->id, 'Users')) ->with('success', trans('admin/users/message.success.update')); } - return redirect()->back()->withInput()->withErrors($user->getErrors()); - - - } - - return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found', compact('id'))); } /** diff --git a/app/Http/Requests/SaveUserRequest.php b/app/Http/Requests/SaveUserRequest.php index b38193c15a..f77defb0b0 100644 --- a/app/Http/Requests/SaveUserRequest.php +++ b/app/Http/Requests/SaveUserRequest.php @@ -31,9 +31,19 @@ class SaveUserRequest extends FormRequest */ public function rules() { + //dd($this->user); $rules = [ 'department_id' => 'nullable|exists:departments,id', 'manager_id' => 'nullable|exists:users,id', + 'company_id' => [ + // determines if the user is being moved between companies and checks to see if they have any items assigned + function ($attribute, $value, $fail) { + dd($this->user); + if (($this->has('company_id')) && ($this->user->allAssignedCount() > 0) && (Setting::getSettings()->full_multiple_companies_support)) { + $fail(trans('admin/users/message.error.multi_company_items_assigned')); + } + } + ] ]; switch ($this->method()) { diff --git a/routes/web/users.php b/routes/web/users.php index 95de200638..3bf1555cad 100644 --- a/routes/web/users.php +++ b/routes/web/users.php @@ -145,10 +145,13 @@ Route::group(['prefix' => 'users', 'middleware' => ['auth']], function () { ] )->name('users/bulkeditsave'); - + // pulling this out of the resource because I need route model binding in the request + Route::patch('/{user}', [Users\UsersController::class, 'update'])->name('users.update'); + Route::put('/{user}', [Users\UsersController::class, 'update'])->name('users.put-update'); }); Route::resource('users', Users\UsersController::class, [ 'middleware' => ['auth'], 'parameters' => ['user' => 'user_id'], + 'except' => ['update'] ]); \ No newline at end of file From f031309f8ffce5747c29e24d467b93cf61ace657 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Wed, 14 Aug 2024 16:09:15 -0500 Subject: [PATCH 07/17] set up api controller for route/model binding --- app/Http/Controllers/Api/UsersController.php | 18 +----------------- app/Http/Requests/SaveUserRequest.php | 1 - 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php index ae6968a475..856b3b6a69 100644 --- a/app/Http/Controllers/Api/UsersController.php +++ b/app/Http/Controllers/Api/UsersController.php @@ -431,9 +431,6 @@ class UsersController extends Controller { $this->authorize('update', User::class); - if ($user = User::find($id)) { - - $this->authorize('update', $user); /** @@ -443,12 +440,10 @@ class UsersController extends Controller * */ - - if ((($id == 1) || ($id == 2)) && (config('app.lock_passwords'))) { + if ((($user->id == 1) || ($user->id == 2)) && (config('app.lock_passwords'))) { return response()->json(Helper::formatStandardApiResponse('error', null, 'Permission denied. You cannot update user information via API on the demo.')); } - $user->fill($request->all()); if ($user->id == $request->input('manager_id')) { @@ -473,16 +468,13 @@ class UsersController extends Controller $user->permissions = $permissions_array; } - // Update the location of any assets checked out to this user Asset::where('assigned_type', User::class) ->where('assigned_to', $user->id)->update(['location_id' => $request->input('location_id', null)]); - app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar'); if ($user->save()) { - // Check if the request has groups passed and has a value, AND that the user us a superuser if (($request->has('groups')) && (auth()->user()->isSuperUser())) { @@ -496,18 +488,10 @@ class UsersController extends Controller // Sync the groups since the user is a superuser and the groups pass validation $user->groups()->sync($request->input('groups')); - - } - return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.success.update'))); } - return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors())); - } - - return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id')))); - } /** diff --git a/app/Http/Requests/SaveUserRequest.php b/app/Http/Requests/SaveUserRequest.php index f77defb0b0..7598e7433d 100644 --- a/app/Http/Requests/SaveUserRequest.php +++ b/app/Http/Requests/SaveUserRequest.php @@ -38,7 +38,6 @@ class SaveUserRequest extends FormRequest 'company_id' => [ // determines if the user is being moved between companies and checks to see if they have any items assigned function ($attribute, $value, $fail) { - dd($this->user); if (($this->has('company_id')) && ($this->user->allAssignedCount() > 0) && (Setting::getSettings()->full_multiple_companies_support)) { $fail(trans('admin/users/message.error.multi_company_items_assigned')); } From afaf53cdfc37d49ba1afbbe178cd974fbb83920f Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Wed, 14 Aug 2024 18:14:21 -0500 Subject: [PATCH 08/17] failing ui test --- resources/views/users/edit.blade.php | 4 ++- routes/web/users.php | 3 +- tests/Feature/Users/Api/UpdateUserTest.php | 30 ++++++++++++++++++++ tests/Feature/Users/Ui/UpdateUserTest.php | 32 ++++++++++++++++++++++ 4 files changed, 66 insertions(+), 3 deletions(-) diff --git a/resources/views/users/edit.blade.php b/resources/views/users/edit.blade.php index e3f691f158..986c18ab6d 100755 --- a/resources/views/users/edit.blade.php +++ b/resources/views/users/edit.blade.php @@ -66,7 +66,9 @@
-
+ {{csrf_field()}} @if($user->id) diff --git a/routes/web/users.php b/routes/web/users.php index 3bf1555cad..e55541a937 100644 --- a/routes/web/users.php +++ b/routes/web/users.php @@ -146,8 +146,7 @@ Route::group(['prefix' => 'users', 'middleware' => ['auth']], function () { )->name('users/bulkeditsave'); // pulling this out of the resource because I need route model binding in the request - Route::patch('/{user}', [Users\UsersController::class, 'update'])->name('users.update'); - Route::put('/{user}', [Users\UsersController::class, 'update'])->name('users.put-update'); + Route::match(['put', 'patch'], '/{user}', [Users\UsersController::class, 'update'])->name('users.update'); }); Route::resource('users', Users\UsersController::class, [ diff --git a/tests/Feature/Users/Api/UpdateUserTest.php b/tests/Feature/Users/Api/UpdateUserTest.php index 1c66bbdda9..2901beea9a 100644 --- a/tests/Feature/Users/Api/UpdateUserTest.php +++ b/tests/Feature/Users/Api/UpdateUserTest.php @@ -2,6 +2,7 @@ namespace Tests\Feature\Users\Api; +use App\Models\Asset; use App\Models\Company; use App\Models\Department; use App\Models\Group; @@ -344,4 +345,33 @@ class UpdateUserTest extends TestCase $this->assertTrue($user->refresh()->groups->contains($groupB)); } + public function testMultiCompanyUserCannotBeMovedIfHasAsset() + { + $this->settings->enableMultipleFullCompanySupport(); + + $companyA = Company::factory()->create(); + $companyB = Company::factory()->create(); + + $user = User::factory()->create([ + 'company_id' => $companyA->id, + ]); + $superUser = User::factory()->superuser()->create(); + + $asset = Asset::factory()->create(); + + // no assets assigned, therefore success + $this->actingAsForApi($superUser)->patchJson(route('api.users.update', $user), [ + 'username' => 'test', + 'company_id' => $companyB->id, + ])->assertStatusMessageIs('success'); + + $asset->checkOut($user, $superUser); + + // asset assigned, therefore error + $this->actingAsForApi($superUser)->patchJson(route('api.users.update', $user), [ + 'username' => 'test', + 'company_id' => $companyB->id, + ])->assertMessagesAre('error'); + } + } diff --git a/tests/Feature/Users/Ui/UpdateUserTest.php b/tests/Feature/Users/Ui/UpdateUserTest.php index bef1d59a06..31530af7c5 100644 --- a/tests/Feature/Users/Ui/UpdateUserTest.php +++ b/tests/Feature/Users/Ui/UpdateUserTest.php @@ -2,6 +2,8 @@ namespace Tests\Feature\Users\Ui; +use App\Models\Asset; +use App\Models\Company; use App\Models\User; use Tests\TestCase; @@ -79,4 +81,34 @@ class UpdateUserTest extends TestCase $this->assertEquals(1, $admin->refresh()->activated); } + + public function testMultiCompanyUserCannotBeMovedIfHasAsset() + { + $this->settings->enableMultipleFullCompanySupport(); + + $companyA = Company::factory()->create(); + $companyB = Company::factory()->create(); + + $user = User::factory()->create([ + 'company_id' => $companyA->id, + ]); + $superUser = User::factory()->superuser()->create(); + + $asset = Asset::factory()->create(); + + // no assets assigned, therefore success + $this->actingAs($superUser)->put(route('users.update', $user), [ + 'first_name' => 'test', + 'username' => 'test', + 'company_id' => $companyB->id, + ])->assertRedirect(route('users.index')); + + //$asset->checkOut($user, $superUser); + + // asset assigned, therefore error + //$this->actingAs($superUser)->patchJson(route('users.update', $user), [ + // 'username' => 'test', + // 'company_id' => $companyB->id, + //])->assertMessagesAre('error'); + } } From 9622e05cf5b545bac1f506af085e6c7e27259848 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Wed, 14 Aug 2024 18:41:06 -0500 Subject: [PATCH 09/17] correct api test --- tests/Feature/Users/Api/UpdateUserTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Feature/Users/Api/UpdateUserTest.php b/tests/Feature/Users/Api/UpdateUserTest.php index 2901beea9a..e7314756dd 100644 --- a/tests/Feature/Users/Api/UpdateUserTest.php +++ b/tests/Feature/Users/Api/UpdateUserTest.php @@ -371,7 +371,7 @@ class UpdateUserTest extends TestCase $this->actingAsForApi($superUser)->patchJson(route('api.users.update', $user), [ 'username' => 'test', 'company_id' => $companyB->id, - ])->assertMessagesAre('error'); + ])->assertStatusMessageIs('error'); } } From dec4691c73b28bab35ed8fdb1ff83578ad517bb0 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Fri, 16 Aug 2024 12:50:09 -0500 Subject: [PATCH 10/17] should be good to go now --- routes/api.php | 8 +++++--- tests/Feature/Users/Api/UpdateUserTest.php | 14 ++++++++++++++ tests/Feature/Users/Ui/UpdateUserTest.php | 21 +++++++++++++-------- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/routes/api.php b/routes/api.php index 0eb0d834cf..c59654d65d 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1070,18 +1070,20 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'throttle:api']], functi ] )->name('api.users.restore'); - }); + }); + + Route::match(['put', 'patch'], '{user}/update', [Api\UsersController::class, 'update']) + ->name('api.users.update'); Route::resource('users', Api\UsersController::class, ['names' => [ 'index' => 'api.users.index', 'show' => 'api.users.show', - 'update' => 'api.users.update', 'store' => 'api.users.store', 'destroy' => 'api.users.destroy', ], - 'except' => ['create', 'edit'], + 'except' => ['create', 'edit', 'update'], 'parameters' => ['user' => 'user_id'], ] ); // end users API routes diff --git a/tests/Feature/Users/Api/UpdateUserTest.php b/tests/Feature/Users/Api/UpdateUserTest.php index e7314756dd..4632a80c3d 100644 --- a/tests/Feature/Users/Api/UpdateUserTest.php +++ b/tests/Feature/Users/Api/UpdateUserTest.php @@ -365,6 +365,13 @@ class UpdateUserTest extends TestCase 'company_id' => $companyB->id, ])->assertStatusMessageIs('success'); + // same test but PUT + $this->actingAsForApi($superUser)->putJson(route('api.users.update', $user), [ + 'username' => 'test', + 'first_name' => 'Test', + 'company_id' => $companyB->id, + ])->assertStatusMessageIs('success'); + $asset->checkOut($user, $superUser); // asset assigned, therefore error @@ -372,6 +379,13 @@ class UpdateUserTest extends TestCase 'username' => 'test', 'company_id' => $companyB->id, ])->assertStatusMessageIs('error'); + + // same test but PUT + $this->actingAsForApi($superUser)->putJson(route('api.users.update', $user), [ + 'username' => 'test', + 'first_name' => 'Test', + 'company_id' => $companyB->id, + ])->assertStatusMessageIs('error'); } } diff --git a/tests/Feature/Users/Ui/UpdateUserTest.php b/tests/Feature/Users/Ui/UpdateUserTest.php index 31530af7c5..3e6867021f 100644 --- a/tests/Feature/Users/Ui/UpdateUserTest.php +++ b/tests/Feature/Users/Ui/UpdateUserTest.php @@ -98,17 +98,22 @@ class UpdateUserTest extends TestCase // no assets assigned, therefore success $this->actingAs($superUser)->put(route('users.update', $user), [ - 'first_name' => 'test', - 'username' => 'test', - 'company_id' => $companyB->id, + 'first_name' => 'test', + 'username' => 'test', + 'company_id' => $companyB->id, + 'redirect_option' => 'index' ])->assertRedirect(route('users.index')); - //$asset->checkOut($user, $superUser); + $asset->checkOut($user, $superUser); // asset assigned, therefore error - //$this->actingAs($superUser)->patchJson(route('users.update', $user), [ - // 'username' => 'test', - // 'company_id' => $companyB->id, - //])->assertMessagesAre('error'); + $response = $this->actingAs($superUser)->patchJson(route('users.update', $user), [ + 'first_name' => 'test', + 'username' => 'test', + 'company_id' => $companyB->id, + 'redirect_option' => 'index' + ]); + + $this->followRedirects($response)->assertSee('error'); } } From 70e5e0f9df91c10d94568c98168be1f5fdc5686a Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Fri, 16 Aug 2024 12:52:06 -0500 Subject: [PATCH 11/17] get rid of dd --- app/Http/Requests/SaveUserRequest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/Http/Requests/SaveUserRequest.php b/app/Http/Requests/SaveUserRequest.php index 7598e7433d..e16826d16c 100644 --- a/app/Http/Requests/SaveUserRequest.php +++ b/app/Http/Requests/SaveUserRequest.php @@ -31,7 +31,6 @@ class SaveUserRequest extends FormRequest */ public function rules() { - //dd($this->user); $rules = [ 'department_id' => 'nullable|exists:departments,id', 'manager_id' => 'nullable|exists:users,id', From a8cd1027f3cc1716b76461f9db7dbc17b8a130b4 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Tue, 20 Aug 2024 11:40:15 -0500 Subject: [PATCH 12/17] rm commented code --- app/Http/Controllers/Users/UsersController.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app/Http/Controllers/Users/UsersController.php b/app/Http/Controllers/Users/UsersController.php index e609727c00..3da0c5a3ac 100755 --- a/app/Http/Controllers/Users/UsersController.php +++ b/app/Http/Controllers/Users/UsersController.php @@ -234,12 +234,7 @@ class UsersController extends Controller $this->authorize('update', $user); - //see if i can get this working at request level - //if ($request->has('company_id') && $user->allAssignedCount() > 0 && Setting::getSettings()->full_multiple_companies_support) { - // return back()->with('error', trans('admin/users/message.multi_company_items_assigned')); - //} - - // Figure out of this user was an admin before this edit + // Figure out of this user was an admin before this edit $orig_permissions_array = $user->decodePermissions(); $orig_superuser = '0'; if (is_array($orig_permissions_array)) { From de0565f5b35ec85cc39a9302637329bba3d4c83a Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 29 Aug 2024 11:24:06 +0100 Subject: [PATCH 13/17] Updated jquery UI Signed-off-by: snipe --- package-lock.json | 9 +- package.json | 2 +- public/js/build/app.js | 4 +- public/js/build/vendor.js | 743 +++++++++++-------------------------- public/js/dist/all.js | 747 +++++++++++--------------------------- public/mix-manifest.json | 6 +- 6 files changed, 431 insertions(+), 1080 deletions(-) diff --git a/package-lock.json b/package-lock.json index f4d51c45a3..30770cde8a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "ekko-lightbox": "^5.1.1", "imagemin": "^8.0.1", "jquery-slimscroll": "^1.3.8", - "jquery-ui": "^1.13.3", + "jquery-ui": "^1.14.0", "jquery-validation": "^1.21.0", "jquery.iframe-transport": "^1.0.0", "jspdf-autotable": "^3.8.2", @@ -7067,10 +7067,11 @@ "license": "BSD-2-Clause" }, "node_modules/jquery-ui": { - "version": "1.13.3", - "license": "MIT", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.14.0.tgz", + "integrity": "sha512-mPfYKBoRCf0MzaT2cyW5i3IuZ7PfTITaasO5OFLAQxrHuI+ZxruPa+4/K1OMNT8oElLWGtIxc9aRbyw20BKr8g==", "dependencies": { - "jquery": ">=1.8.0 <4.0.0" + "jquery": ">=1.12.0 <5.0.0" } }, "node_modules/jquery-validation": { diff --git a/package.json b/package.json index a36144a17b..d0ce13579d 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "ekko-lightbox": "^5.1.1", "imagemin": "^8.0.1", "jquery-slimscroll": "^1.3.8", - "jquery-ui": "^1.13.3", + "jquery-ui": "^1.14.0", "jquery-validation": "^1.21.0", "jquery.iframe-transport": "^1.0.0", "jspdf-autotable": "^3.8.2", diff --git a/public/js/build/app.js b/public/js/build/app.js index c188a713b4..3c80510129 100644 --- a/public/js/build/app.js +++ b/public/js/build/app.js @@ -4047,7 +4047,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ $.ui = $.ui || {}; -return $.ui.version = "1.13.3"; +return $.ui.version = "1.14.0"; } ); @@ -4061,7 +4061,7 @@ return $.ui.version = "1.13.3"; /***/ ((module, exports, __webpack_require__) => { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! - * jQuery UI Widget 1.13.3 + * jQuery UI Widget 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors diff --git a/public/js/build/vendor.js b/public/js/build/vendor.js index 102713f1f3..6f934b73d0 100644 --- a/public/js/build/vendor.js +++ b/public/js/build/vendor.js @@ -12707,14 +12707,14 @@ return Tether; })); -/*! jQuery UI - v1.13.3 - 2024-04-26 +/*! jQuery UI - v1.14.0 - 2024-08-05 * https://jqueryui.com * Includes: widget.js, position.js, data.js, disable-selection.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js, focusable.js, form-reset-mixin.js, jquery-patch.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js * Copyright OpenJS Foundation and other contributors; Licensed MIT */ ( function( factory ) { "use strict"; - + if ( typeof define === "function" && define.amd ) { // AMD. Register as an anonymous module. @@ -12729,11 +12729,11 @@ return Tether; $.ui = $.ui || {}; -var version = $.ui.version = "1.13.3"; +var version = $.ui.version = "1.14.0"; /*! - * jQuery UI Widget 1.13.3 + * jQuery UI Widget 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -13475,7 +13475,7 @@ var widget = $.widget; /*! - * jQuery UI Position 1.13.3 + * jQuery UI Position 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -13972,7 +13972,7 @@ var position = $.ui.position; /*! - * jQuery UI :data 1.13.3 + * jQuery UI :data 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -13987,21 +13987,15 @@ var position = $.ui.position; var data = $.extend( $.expr.pseudos, { - data: $.expr.createPseudo ? - $.expr.createPseudo( function( dataName ) { - return function( elem ) { - return !!$.data( elem, dataName ); - }; - } ) : - - // Support: jQuery <1.8 - function( elem, i, match ) { - return !!$.data( elem, match[ 3 ] ); - } + data: $.expr.createPseudo( function( dataName ) { + return function( elem ) { + return !!$.data( elem, dataName ); + }; + } ) } ); /*! - * jQuery UI Disable Selection 1.13.3 + * jQuery UI Disable Selection 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -14044,18 +14038,17 @@ var jQuery = $; /*! - * jQuery Color Animations v2.2.0 + * jQuery Color Animations v3.0.0 * https://github.com/jquery/jquery-color * * Copyright OpenJS Foundation and other contributors * Released under the MIT license. * https://jquery.org/license * - * Date: Sun May 10 09:02:36 2020 +0200 + * Date: Wed May 15 16:49:44 2024 +0200 */ - var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " + "borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", @@ -14180,10 +14173,6 @@ var jQuery = $; floor: true } }, - support = color.support = {}, - - // element for support tests - supportElem = jQuery( "

" )[ 0 ], // colors = jQuery.Color.names colors, @@ -14191,10 +14180,6 @@ var jQuery = $; // local aliases of functions called often each = jQuery.each; -// determine rgba support immediately -supportElem.style.cssText = "background-color:rgba(1,1,1,.5)"; -support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1; - // define cache name and alpha properties // for rgba and hsla spaces each( spaces, function( spaceName, space ) { @@ -14232,12 +14217,6 @@ function clamp( value, prop, allowEmpty ) { // ~~ is an short way of doing floor for positive numbers value = type.floor ? ~~value : parseFloat( value ); - // IE will pass in empty strings as value for alpha, - // which will hit this case - if ( isNaN( value ) ) { - return prop.def; - } - if ( type.mod ) { // we add mod before modding to make sure that negatives values @@ -14350,7 +14329,10 @@ color.fn = jQuery.extend( color.prototype, { } ); // everything defined but alpha? - if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { + if ( inst[ cache ] && jQuery.inArray( + null, + inst[ cache ].slice( 0, 3 ) + ) < 0 ) { // use the default of 1 if ( inst[ cache ][ 3 ] == null ) { @@ -14462,7 +14444,7 @@ color.fn = jQuery.extend( color.prototype, { prefix = "rgb("; } - return prefix + rgba.join() + ")"; + return prefix + rgba.join( ", " ) + ")"; }, toHslaString: function() { var prefix = "hsla(", @@ -14482,7 +14464,7 @@ color.fn = jQuery.extend( color.prototype, { hsla.pop(); prefix = "hsl("; } - return prefix + hsla.join() + ")"; + return prefix + hsla.join( ", " ) + ")"; }, toHexString: function( includeAlpha ) { var rgba = this._rgba.slice(), @@ -14495,12 +14477,11 @@ color.fn = jQuery.extend( color.prototype, { return "#" + jQuery.map( rgba, function( v ) { // default to 0 when nulls exist - v = ( v || 0 ).toString( 16 ); - return v.length === 1 ? "0" + v : v; + return ( "0" + ( v || 0 ).toString( 16 ) ).substr( -2 ); } ).join( "" ); }, toString: function() { - return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString(); + return this.toRgbaString(); } } ); color.fn.parse.prototype = color.fn; @@ -14667,37 +14648,15 @@ color.hook = function( hook ) { each( hooks, function( _i, hook ) { jQuery.cssHooks[ hook ] = { set: function( elem, value ) { - var parsed, curElem, - backgroundColor = ""; + var parsed; - if ( value !== "transparent" && ( getType( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) { + if ( value !== "transparent" && + ( getType( value ) !== "string" || + ( parsed = stringParse( value ) ) ) ) { value = color( parsed || value ); - if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { - curElem = hook === "backgroundColor" ? elem.parentNode : elem; - while ( - ( backgroundColor === "" || backgroundColor === "transparent" ) && - curElem && curElem.style - ) { - try { - backgroundColor = jQuery.css( curElem, "backgroundColor" ); - curElem = curElem.parentNode; - } catch ( e ) { - } - } - - value = value.blend( backgroundColor && backgroundColor !== "transparent" ? - backgroundColor : - "_default" ); - } - value = value.toRgbaString(); } - try { - elem.style[ hook ] = value; - } catch ( e ) { - - // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit' - } + elem.style[ hook ] = value; } }; jQuery.fx.step[ hook ] = function( fx ) { @@ -14756,7 +14715,7 @@ colors = jQuery.Color.names = { /*! - * jQuery UI Effects 1.13.3 + * jQuery UI Effects 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -14819,26 +14778,14 @@ function camelCase( string ) { function getElementStyles( elem ) { var key, len, - style = elem.ownerDocument.defaultView ? - elem.ownerDocument.defaultView.getComputedStyle( elem, null ) : - elem.currentStyle, + style = elem.ownerDocument.defaultView.getComputedStyle( elem ), styles = {}; - if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { - len = style.length; - while ( len-- ) { - key = style[ len ]; - if ( typeof style[ key ] === "string" ) { - styles[ camelCase( key ) ] = style[ key ]; - } - } - - // Support: Opera, IE <9 - } else { - for ( key in style ) { - if ( typeof style[ key ] === "string" ) { - styles[ key ] = style[ key ]; - } + len = style.length; + while ( len-- ) { + key = style[ len ]; + if ( typeof style[ key ] === "string" ) { + styles[ camelCase( key ) ] = style[ key ]; } } @@ -14863,15 +14810,6 @@ function styleDifference( oldStyle, newStyle ) { return diff; } -// Support: jQuery <1.8 -if ( !$.fn.addBack ) { - $.fn.addBack = function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter( selector ) - ); - }; -} - $.effects.animateClass = function( value, duration, easing, callback ) { var o = $.speed( duration, easing, callback ); @@ -15011,7 +14949,7 @@ if ( $.expr && $.expr.pseudos && $.expr.pseudos.animated ) { } )( $.expr.pseudos.animated ); } -if ( $.uiBackCompat !== false ) { +if ( $.uiBackCompat === true ) { $.extend( $.effects, { // Saves a set of properties in a data storage @@ -15140,7 +15078,7 @@ if ( $.uiBackCompat !== false ) { } $.extend( $.effects, { - version: "1.13.3", + version: "1.14.0", define: function( name, mode, effect ) { if ( !effect ) { @@ -15497,7 +15435,7 @@ $.fn.extend( { // as toggle can be either show or hide depending on element state args.mode = modes.shift(); - if ( $.uiBackCompat !== false && !defaultMode ) { + if ( $.uiBackCompat === true && !defaultMode ) { if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { // Call the core method to track "olddisplay" properly @@ -15708,7 +15646,7 @@ var effect = $.effects; /*! - * jQuery UI Effects Blind 1.13.3 + * jQuery UI Effects Blind 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -15763,7 +15701,7 @@ var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, d /*! - * jQuery UI Effects Bounce 1.13.3 + * jQuery UI Effects Bounce 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -15858,7 +15796,7 @@ var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) /*! - * jQuery UI Effects Clip 1.13.3 + * jQuery UI Effects Clip 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -15908,7 +15846,7 @@ var effectsEffectClip = $.effects.define( "clip", "hide", function( options, don /*! - * jQuery UI Effects Drop 1.13.3 + * jQuery UI Effects Drop 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -15962,7 +15900,7 @@ var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, don /*! - * jQuery UI Effects Explode 1.13.3 + * jQuery UI Effects Explode 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -16058,7 +15996,7 @@ var effectsEffectExplode = $.effects.define( "explode", "hide", function( option /*! - * jQuery UI Effects Fade 1.13.3 + * jQuery UI Effects Fade 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -16090,7 +16028,7 @@ var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, d /*! - * jQuery UI Effects Fold 1.13.3 + * jQuery UI Effects Fold 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -16164,7 +16102,7 @@ var effectsEffectFold = $.effects.define( "fold", "hide", function( options, don /*! - * jQuery UI Effects Highlight 1.13.3 + * jQuery UI Effects Highlight 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -16206,7 +16144,7 @@ var effectsEffectHighlight = $.effects.define( "highlight", "show", function( op /*! - * jQuery UI Effects Size 1.13.3 + * jQuery UI Effects Size 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -16384,7 +16322,7 @@ var effectsEffectSize = $.effects.define( "size", function( options, done ) { /*! - * jQuery UI Effects Scale 1.13.3 + * jQuery UI Effects Scale 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -16424,7 +16362,7 @@ var effectsEffectScale = $.effects.define( "scale", function( options, done ) { /*! - * jQuery UI Effects Puff 1.13.3 + * jQuery UI Effects Puff 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -16450,7 +16388,7 @@ var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, don /*! - * jQuery UI Effects Pulsate 1.13.3 + * jQuery UI Effects Pulsate 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -16499,7 +16437,7 @@ var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( option /*! - * jQuery UI Effects Shake 1.13.3 + * jQuery UI Effects Shake 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -16558,7 +16496,7 @@ var effectsEffectShake = $.effects.define( "shake", function( options, done ) { /*! - * jQuery UI Effects Slide 1.13.3 + * jQuery UI Effects Slide 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -16619,7 +16557,7 @@ var effectsEffectSlide = $.effects.define( "slide", "show", function( options, d /*! - * jQuery UI Effects Transfer 1.13.3 + * jQuery UI Effects Transfer 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -16635,7 +16573,7 @@ var effectsEffectSlide = $.effects.define( "slide", "show", function( options, d var effect; -if ( $.uiBackCompat !== false ) { +if ( $.uiBackCompat === true ) { effect = $.effects.define( "transfer", function( options, done ) { $( this ).transfer( options, done ); } ); @@ -16644,7 +16582,7 @@ var effectsEffectTransfer = effect; /*! - * jQuery UI Focusable 1.13.3 + * jQuery UI Focusable 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -16693,20 +16631,10 @@ $.ui.focusable = function( element, hasTabindex ) { focusableIfVisible = hasTabindex; } - return focusableIfVisible && $( element ).is( ":visible" ) && visible( $( element ) ); + return focusableIfVisible && $( element ).is( ":visible" ) && + $( element ).css( "visibility" ) === "visible"; }; -// Support: IE 8 only -// IE 8 doesn't resolve inherit to visible/hidden for computed values -function visible( element ) { - var visibility = element.css( "visibility" ); - while ( visibility === "inherit" ) { - element = element.parent(); - visibility = element.css( "visibility" ); - } - return visibility === "visible"; -} - $.extend( $.expr.pseudos, { focusable: function( element ) { return $.ui.focusable( element, $.attr( element, "tabindex" ) != null ); @@ -16716,17 +16644,8 @@ $.extend( $.expr.pseudos, { var focusable = $.ui.focusable; - -// Support: IE8 Only -// IE8 does not support the form attribute and when it is supplied. It overwrites the form prop -// with a string, so we need to find the proper form. -var form = $.fn._form = function() { - return typeof this[ 0 ].form === "string" ? this.closest( "form" ) : $( this[ 0 ].form ); -}; - - /*! - * jQuery UI Form Reset Mixin 1.13.3 + * jQuery UI Form Reset Mixin 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -16754,7 +16673,7 @@ var formResetMixin = $.ui.formResetMixin = { }, _bindFormResetHandler: function() { - this.form = this.element._form(); + this.form = $( this.element.prop( "form" ) ); if ( !this.form.length ) { return; } @@ -16788,7 +16707,7 @@ var formResetMixin = $.ui.formResetMixin = { /*! - * jQuery UI Support for jQuery core 1.8.x and newer 1.13.3 + * jQuery UI Legacy jQuery Core patches 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -16797,50 +16716,17 @@ var formResetMixin = $.ui.formResetMixin = { * */ -//>>label: jQuery 1.8+ Support +//>>label: Legacy jQuery Core patches //>>group: Core -//>>description: Support version 1.8.x and newer of jQuery core +//>>description: Backport `.even()`, `.odd()` and `$.escapeSelector` to older jQuery Core versions (deprecated) -// Support: jQuery 1.9.x or older -// $.expr[ ":" ] is deprecated. -if ( !$.expr.pseudos ) { - $.expr.pseudos = $.expr[ ":" ]; -} - -// Support: jQuery 1.11.x or older -// $.unique has been renamed to $.uniqueSort -if ( !$.uniqueSort ) { - $.uniqueSort = $.unique; -} - // Support: jQuery 2.2.x or older. // This method has been defined in jQuery 3.0.0. // Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js if ( !$.escapeSelector ) { - - // CSS string/identifier serialization - // https://drafts.csswg.org/cssom/#common-serializing-idioms - var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g; - - var fcssescape = function( ch, asCodePoint ) { - if ( asCodePoint ) { - - // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER - if ( ch === "\0" ) { - return "\uFFFD"; - } - - // Control characters and (dependent upon position) numbers get escaped as code points - return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; - } - - // Other potentially-special ASCII characters get backslash-escaped - return "\\" + ch; - }; - - $.escapeSelector = function( sel ) { - return ( sel + "" ).replace( rcssescape, fcssescape ); + $.escapeSelector = function( id ) { + return CSS.escape( id + "" ); }; } @@ -16863,7 +16749,7 @@ if ( !$.fn.even || !$.fn.odd ) { ; /*! - * jQuery UI Keycode 1.13.3 + * jQuery UI Keycode 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -16898,7 +16784,7 @@ var keycode = $.ui.keyCode = { /*! - * jQuery UI Labels 1.13.3 + * jQuery UI Labels 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -16924,9 +16810,8 @@ var labels = $.fn.labels = function() { return this.pushStack( this[ 0 ].labels ); } - // Support: IE <= 11, FF <= 37, Android <= 2.3 only - // Above browsers do not support control.labels. Everything below is to support them - // as well as document fragments. control.labels does not work on document fragments + // If `control.labels` is empty - e.g. inside of document fragments - find + // the labels manually labels = this.eq( 0 ).parents( "label" ); // Look for the label based on the id @@ -16941,7 +16826,7 @@ var labels = $.fn.labels = function() { ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() ); // Create a selector for the label based on the id - selector = "label[for='" + $.escapeSelector( id ) + "']"; + selector = "label[for='" + CSS.escape( id ) + "']"; labels = labels.add( ancestors.find( selector ).addBack( selector ) ); @@ -16953,7 +16838,7 @@ var labels = $.fn.labels = function() { /*! - * jQuery UI Scroll Parent 1.13.3 + * jQuery UI Scroll Parent 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -16987,7 +16872,7 @@ var scrollParent = $.fn.scrollParent = function( includeHidden ) { /*! - * jQuery UI Tabbable 1.13.3 + * jQuery UI Tabbable 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -17011,7 +16896,7 @@ var tabbable = $.extend( $.expr.pseudos, { /*! - * jQuery UI Unique ID 1.13.3 + * jQuery UI Unique ID 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -17049,7 +16934,7 @@ var uniqueId = $.fn.extend( { /*! - * jQuery UI Accordion 1.13.3 + * jQuery UI Accordion 1.14.0 * https://jqueryui.com * * Copyright OpenJS Foundation and other contributors @@ -17070,7 +16955,7 @@ var uniqueId = $.fn.extend( { var widgetsAccordion = $.widget( "ui.accordion", { - version: "1.13.3", + version: "1.14.0", options: { active: 0, animate: {}, @@ -17082,7 +16967,17 @@ var widgetsAccordion = $.widget( "ui.accordion", { collapsible: false, event: "click", header: function( elem ) { - return elem.find( "> li > :first-child" ).add( elem.find( "> :not(li)" ).even() ); + return elem + .find( "> li > :first-child" ) + .add( + elem.find( "> :not(li)" ) + + // Support: jQuery <3.5 only + // We could use `.even()` but that's unavailable in older jQuery. + .filter( function( i ) { + return i % 2 === 0; + } ) + ); }, heightStyle: "auto", icons: { @@ -17217,13 +17112,7 @@ var widgetsAccordion = $.widget( "ui.accordion", { this._super( value ); this.element.attr( "aria-disabled", value ); - - // Support: IE8 Only - // #5332 / #6059 - opacity doesn't cascade to positioned elements in IE - // so we need to add the disabled class to the headers and panels this._toggleClass( null, "ui-state-disabled", !!value ); - this._toggleClass( this.headers.add( this.headers.next() ), null, "ui-state-disabled", - !!value ); }, _keydown: function( event ) { @@ -17641,47 +17530,13 @@ var widgetsAccordion = $.widget( "ui.accordion", { this._removeClass( prev, "ui-accordion-header-active" ) ._addClass( prev, "ui-accordion-header-collapsed" ); - // Work around for rendering bug in IE (#5421) - if ( toHide.length ) { - toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className; - } this._trigger( "activate", null, data ); } } ); - -var safeActiveElement = $.ui.safeActiveElement = function( document ) { - var activeElement; - - // Support: IE 9 only - // IE9 throws an "Unspecified error" accessing document.activeElement from an