Skip to content

Commit

Permalink
Merge branch 'develop' into fix_unclickable_nav_bar_and_notifcation_b…
Browse files Browse the repository at this point in the history
…lock
  • Loading branch information
snipe committed May 24, 2023
2 parents 68a43cb + 2e5486a commit 9086cb5
Show file tree
Hide file tree
Showing 11 changed files with 136 additions and 22 deletions.
11 changes: 8 additions & 3 deletions app/Models/Asset.php
Original file line number Diff line number Diff line change
Expand Up @@ -947,8 +947,10 @@ public function advancedTextSearch(Builder $query, array $terms)
->orWhere('assets_users.first_name', 'LIKE', '%'.$term.'%')
->orWhere('assets_users.last_name', 'LIKE', '%'.$term.'%')
->orWhere('assets_users.username', 'LIKE', '%'.$term.'%')
->orWhereRaw('CONCAT('.DB::getTablePrefix().'assets_users.first_name," ",'.DB::getTablePrefix().'assets_users.last_name) LIKE ?', ["%$term%"]);

->orWhereMultipleColumns([
'assets_users.first_name',
'assets_users.last_name',
], $term);
}

/**
Expand Down Expand Up @@ -1343,7 +1345,10 @@ public function scopeAssignedSearch($query, $search)
})->orWhere(function ($query) use ($search) {
$query->where('assets_users.first_name', 'LIKE', '%'.$search.'%')
->orWhere('assets_users.last_name', 'LIKE', '%'.$search.'%')
->orWhereRaw('CONCAT('.DB::getTablePrefix().'assets_users.first_name," ",'.DB::getTablePrefix().'assets_users.last_name) LIKE ?', ["%$search%"])
->orWhereMultipleColumns([
'assets_users.first_name',
'assets_users.last_name',
], $search)
->orWhere('assets_users.username', 'LIKE', '%'.$search.'%')
->orWhere('assets_locations.name', 'LIKE', '%'.$search.'%')
->orWhere('assigned_assets.name', 'LIKE', '%'.$search.'%');
Expand Down
42 changes: 41 additions & 1 deletion app/Models/Traits/Searchable.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use App\Models\Asset;
use App\Models\CustomField;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;

/**
* This trait allows for cleaner searching of models,
Expand Down Expand Up @@ -164,7 +165,13 @@ private function searchRelations(Builder $query, array $terms)
}
// I put this here because I only want to add the concat one time in the end of the user relation search
if($relation == 'user') {
$query->orWhereRaw('CONCAT (users.first_name, " ", users.last_name) LIKE ?', ["%{$term}%"]);
$query->orWhereRaw(
$this->buildMultipleColumnSearch([
'users.first_name',
'users.last_name',
]),
["%{$term}%"]
);
}
});
}
Expand Down Expand Up @@ -257,4 +264,37 @@ private function getRelationTable($relation)

return $related->getTable();
}

/**
* Builds a search string for either MySQL or sqlite by separating the provided columns with a space.
*
* @param array $columns Columns to include in search string.
* @return string
*/
private function buildMultipleColumnSearch(array $columns): string
{
$mappedColumns = collect($columns)->map(fn($column) => DB::getTablePrefix() . $column)->toArray();

$driver = config('database.connections.' . config('database.default') . '.driver');

if ($driver === 'sqlite') {
return implode("||' '||", $mappedColumns) . ' LIKE ?';
}

// Default to MySQL's concatenation method
return 'CONCAT(' . implode('," ",', $mappedColumns) . ') LIKE ?';
}

/**
* Search a string across multiple columns separated with a space.
*
* @param Builder $query
* @param array $columns - Columns to include in search string.
* @param $term
* @return Builder
*/
public function scopeOrWhereMultipleColumns($query, array $columns, $term)
{
return $query->orWhereRaw($this->buildMultipleColumnSearch($columns), ["%{$term}%"]);
}
}
18 changes: 10 additions & 8 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -644,14 +644,14 @@ public function decodePermissions()
*/
public function scopeSimpleNameSearch($query, $search)
{
$query = $query->where('first_name', 'LIKE', '%'.$search.'%')
->orWhere('last_name', 'LIKE', '%'.$search.'%')
->orWhereRaw('CONCAT('.DB::getTablePrefix().'users.first_name," ",'.DB::getTablePrefix().'users.last_name) LIKE ?', ["%{$search}%"]);

return $query;
return $query->where('first_name', 'LIKE', '%' . $search . '%')
->orWhere('last_name', 'LIKE', '%' . $search . '%')
->orWhereMultipleColumns([
'users.first_name',
'users.last_name',
], $search);
}


/**
* Run additional, advanced searches.
*
Expand All @@ -660,9 +660,11 @@ public function scopeSimpleNameSearch($query, $search)
* @return \Illuminate\Database\Eloquent\Builder
*/
public function advancedTextSearch(Builder $query, array $terms) {

foreach($terms as $term) {
$query = $query->orWhereRaw('CONCAT('.DB::getTablePrefix().'users.first_name," ",'.DB::getTablePrefix().'users.last_name) LIKE ?', ["%{$term}%"]);
$query->orWhereMultipleColumns([
'users.first_name',
'users.last_name',
], $term);
}

return $query;
Expand Down
24 changes: 17 additions & 7 deletions database/seeders/CustomFieldSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,24 +38,34 @@ public function run()
[
'custom_field_id' => '1',
'custom_fieldset_id' => '1',
'order' => 0,
'required' => 0,
],
[
'custom_field_id' => '2',
'custom_fieldset_id' => '1',
'order' => 0,
'required' => 0,
],
[
'custom_field_id' => '3',
'custom_fieldset_id' => '2',
'custom_field_id' => '3',
'custom_fieldset_id' => '2',
'order' => 0,
'required' => 0,
],
[
'custom_field_id' => '4',
'custom_fieldset_id' => '2',
'custom_field_id' => '4',
'custom_fieldset_id' => '2',
'order' => 0,
'required' => 0,
],
[
'custom_field_id' => '5',
'custom_fieldset_id' => '2',
'custom_field_id' => '5',
'custom_fieldset_id' => '2',
'order' => 0,
'required' => 0,
],

]);
]);
}
}
3 changes: 3 additions & 0 deletions public/css/build/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -1104,6 +1104,9 @@ input[type="radio"]:checked::before {
grid-template-columns: 0.1em auto;
gap: 1.5em;
}
.select2-container .select2-search--inline .select2-search__field {
padding-left: 15px;
}
/** --------------------------------------- **/
/** End checkbox styles to replace iCheck **/
/** --------------------------------------- **/
Expand Down
3 changes: 3 additions & 0 deletions public/css/build/overrides.css
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,9 @@ input[type="radio"]:checked::before {
grid-template-columns: 0.1em auto;
gap: 1.5em;
}
.select2-container .select2-search--inline .select2-search__field {
padding-left: 15px;
}
/** --------------------------------------- **/
/** End checkbox styles to replace iCheck **/
/** --------------------------------------- **/
Expand Down
6 changes: 6 additions & 0 deletions public/css/dist/all.css
Original file line number Diff line number Diff line change
Expand Up @@ -23870,6 +23870,9 @@ input[type="radio"]:checked::before {
grid-template-columns: 0.1em auto;
gap: 1.5em;
}
.select2-container .select2-search--inline .select2-search__field {
padding-left: 15px;
}
/** --------------------------------------- **/
/** End checkbox styles to replace iCheck **/
/** --------------------------------------- **/
Expand Down Expand Up @@ -25096,6 +25099,9 @@ input[type="radio"]:checked::before {
grid-template-columns: 0.1em auto;
gap: 1.5em;
}
.select2-container .select2-search--inline .select2-search__field {
padding-left: 15px;
}
/** --------------------------------------- **/
/** End checkbox styles to replace iCheck **/
/** --------------------------------------- **/
Expand Down
6 changes: 3 additions & 3 deletions public/mix-manifest.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"/js/build/app.js": "/js/build/app.js?id=7caeae38608edd96421f8ef59d33f5f6",
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=f677207c6cf9678eb539abecb408c374",
"/css/build/overrides.css": "/css/build/overrides.css?id=97a58ce3a89cd0043a1c54ecf63d4686",
"/css/build/app.css": "/css/build/app.css?id=02dbcc25fce08e9b9a9b285883821805",
"/css/build/overrides.css": "/css/build/overrides.css?id=eb44bf9eb12277e0dc680c6d498ee6af",
"/css/build/app.css": "/css/build/app.css?id=62fd4966017ec9d8740b21869eca4302",
"/css/build/AdminLTE.css": "/css/build/AdminLTE.css?id=dc383f8560a8d4adb51d44fb4043e03b",
"/css/dist/skins/skin-orange.css": "/css/dist/skins/skin-orange.css?id=6f0563e726c2fe4fab4026daaa5bfdf2",
"/css/dist/skins/skin-orange-dark.css": "/css/dist/skins/skin-orange-dark.css?id=e6e53eef152bba01a4c666a4d8b01117",
Expand All @@ -18,7 +18,7 @@
"/css/dist/skins/skin-green.css": "/css/dist/skins/skin-green.css?id=0a82a6ae6bb4e58fe62d162c4fb50397",
"/css/dist/skins/skin-contrast.css": "/css/dist/skins/skin-contrast.css?id=da6c7997d9de2f8329142399f0ce50da",
"/css/dist/skins/skin-red.css": "/css/dist/skins/skin-red.css?id=44bf834f2110504a793dadec132a5898",
"/css/dist/all.css": "/css/dist/all.css?id=999cf8c1432f7baff31b61a04a9a8485",
"/css/dist/all.css": "/css/dist/all.css?id=654fb4ff3970fdd2f3094090ab18d098",
"/css/dist/signature-pad.css": "/css/dist/signature-pad.css?id=6a89d3cd901305e66ced1cf5f13147f7",
"/css/dist/signature-pad.min.css": "/css/dist/signature-pad.min.css?id=6a89d3cd901305e66ced1cf5f13147f7",
"/css/webfonts/fa-brands-400.ttf": "/css/webfonts/fa-brands-400.ttf?id=e2e2b1797606a266ed55549f5bb5a179",
Expand Down
4 changes: 4 additions & 0 deletions resources/assets/less/overrides.less
Original file line number Diff line number Diff line change
Expand Up @@ -844,8 +844,12 @@ input[type="radio"]:checked::before {
grid-template-columns: .1em auto;
gap: 1.5em;
}

.nav-tabs-custom > .nav-tabs > li {
z-index:1;

.select2-container .select2-search--inline .select2-search__field{
padding-left:15px;
}

/** --------------------------------------- **/
Expand Down
13 changes: 13 additions & 0 deletions tests/Feature/Api/Users/UsersForSelectListTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,19 @@ public function testUsersAreReturned()
->assertJson(fn(AssertableJson $json) => $json->has('results', 3)->etc());
}

public function testUsersCanBeSearchedByFirstAndLastName()
{
User::factory()->create(['first_name' => 'Luke', 'last_name' => 'Skywalker']);

Passport::actingAs(User::factory()->create());
$response = $this->getJson(route('api.users.selectlist', ['search' => 'luke sky']))->assertOk();

$results = collect($response->json('results'));

$this->assertEquals(1, $results->count());
$this->assertTrue($results->pluck('text')->contains(fn($text) => str_contains($text, 'Luke')));
}

public function testUsersScopedToCompanyWhenMultipleFullCompanySupportEnabled()
{
$this->settings->enableMultipleFullCompanySupport();
Expand Down
28 changes: 28 additions & 0 deletions tests/Feature/Api/Users/UsersSearchTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Tests\Feature\Api\Users;

use App\Models\User;
use Laravel\Passport\Passport;
use Tests\Support\InteractsWithSettings;
use Tests\TestCase;

class UsersSearchTest extends TestCase
{
use InteractsWithSettings;

public function testCanSearchByUserFirstAndLastName()
{
User::factory()->create(['first_name' => 'Luke', 'last_name' => 'Skywalker']);
User::factory()->create(['first_name' => 'Darth', 'last_name' => 'Vader']);

Passport::actingAs(User::factory()->viewUsers()->create());
$response = $this->getJson(route('api.users.index', ['search' => 'luke sky']))->assertOk();

$results = collect($response->json('rows'));

$this->assertEquals(1, $results->count());
$this->assertTrue($results->pluck('name')->contains(fn($text) => str_contains($text, 'Luke')));
$this->assertFalse($results->pluck('name')->contains(fn($text) => str_contains($text, 'Darth')));
}
}

0 comments on commit 9086cb5

Please sign in to comment.