]> BookStack Code Mirror - bookstack/commitdiff
Added pagination, sorting & searching to users list
authorDan Brown <redacted>
Sun, 22 May 2016 09:44:31 +0000 (10:44 +0100)
committerDan Brown <redacted>
Sun, 22 May 2016 09:44:31 +0000 (10:44 +0100)
As requested on #113

app/Http/Controllers/UserController.php
app/Repos/UserRepo.php
app/helpers.php
resources/assets/sass/_lists.scss
resources/assets/sass/_text.scss
resources/views/settings/roles/index.blade.php
resources/views/users/index.blade.php

index d1c8865a95d50f430bb5ca63441a12539792cb7a..053d9ebd57345017cb9f8faf22986de52335cf63 100644 (file)
@@ -31,14 +31,21 @@ class UserController extends Controller
 
     /**
      * Display a listing of the users.
+     * @param Request $request
      * @return Response
      */
-    public function index()
+    public function index(Request $request)
     {
         $this->checkPermission('users-manage');
-        $users = $this->userRepo->getAllUsers();
+        $listDetails = [
+            'order' => $request->has('order') ? $request->get('order') : 'asc',
+            'search' => $request->has('search') ? $request->get('search') : '',
+            'sort' => $request->has('sort') ? $request->get('sort') : 'name',
+        ];
+        $users = $this->userRepo->getAllUsersPaginatedAndSorted(20, $listDetails);
         $this->setPageTitle('Users');
-        return view('users/index', ['users' => $users]);
+        $users->appends($listDetails);
+        return view('users/index', ['users' => $users, 'listDetails' => $listDetails]);
     }
 
     /**
index b4931bdffbd859222238bcefbfa56c0fd3cbb2cb..0926f630471c24e1583b937e91ce74f2414d5da9 100644 (file)
@@ -51,6 +51,27 @@ class UserRepo
         return $this->user->with('roles', 'avatar')->orderBy('name', 'asc')->get();
     }
 
+    /**
+     * Get all the users with their permissions in a paginated format.
+     * @param int $count
+     * @param $sortData
+     * @return \Illuminate\Database\Eloquent\Builder|static
+     */
+    public function getAllUsersPaginatedAndSorted($count = 20, $sortData)
+    {
+        $query = $this->user->with('roles', 'avatar')->orderBy($sortData['sort'], $sortData['order']);
+
+        if ($sortData['search']) {
+            $term = '%' . $sortData['search'] . '%';
+            $query->where(function($query) use ($term) {
+                $query->where('name', 'like', $term)
+                    ->orWhere('email', 'like', $term);
+            });
+        }
+
+        return $query->paginate($count);
+    }
+
     /**
      * Creates a new user and attaches a role to them.
      * @param array $data
index fea67a09a4c8d047ac52617a1831f5bee0ef33bf..b8f61d94e3fde57f757c115b5f45c4fa0dc84080 100644 (file)
@@ -59,3 +59,35 @@ function setting($key, $default = false)
     $settingService = app('BookStack\Services\SettingService');
     return $settingService->get($key, $default);
 }
+
+/**
+ * Generate a url with multiple parameters for sorting purposes.
+ * Works out the logic to set the correct sorting direction
+ * Discards empty parameters and allows overriding.
+ * @param $path
+ * @param array $data
+ * @param array $overrideData
+ * @return string
+ */
+function sortUrl($path, $data, $overrideData = [])
+{
+    $queryStringSections = [];
+    $queryData = array_merge($data, $overrideData);
+    
+    // Change sorting direction is already sorted on current attribute
+    if (isset($overrideData['sort']) && $overrideData['sort'] === $data['sort']) {
+        $queryData['order'] = ($data['order'] === 'asc') ? 'desc' : 'asc';
+    } else {
+        $queryData['order'] = 'asc';
+    }
+    
+    foreach ($queryData as $name => $value) {
+        $trimmedVal = trim($value);
+        if ($trimmedVal === '') continue;
+        $queryStringSections[] = urlencode($name) . '=' . urlencode($trimmedVal);
+    }
+
+    if (count($queryStringSections) === 0) return $path;
+
+    return $path . '?' . implode('&', $queryStringSections);
+}
\ No newline at end of file
index 6794433138b8b7bab52d780e2a1942cc6f7493f0..388d5753da1fd0e186117228ca417a7c7faf5527 100644 (file)
@@ -266,6 +266,7 @@ ul.pagination {
   display: inline-block;
   list-style: none;
   margin: $-m 0;
+  padding-left: 1px;
   li {
     float: left;
   }
@@ -300,6 +301,10 @@ ul.pagination {
   }
 }
 
+.compact ul.pagination {
+  margin: 0;
+}
+
 .entity-list {
   >div {
     padding: $-m 0;
index 1a55cf86818ff41b90d81420c4f23b21b4ef86ae..0095b91cbf792adaa5764101732cfc8201c9f4bb 100644 (file)
@@ -297,6 +297,12 @@ span.sep {
   display: block;
 }
 
+.action-header {
+  h1 {
+    margin-top: $-m;
+  }
+}
+
 /**
   * Icons
   */
index 8f92a5eba4a12c45ef4713d4325be6769ec1fc7f..358c24945e79bfc86c8d779fdcd64b481ff3de03 100644 (file)
@@ -6,11 +6,15 @@
 
     <div class="container small">
 
-        <h1>User Roles</h1>
-
-        <p>
-            <a href="/settings/roles/new" class="text-pos"><i class="zmdi zmdi-lock-open"></i>Add new role</a>
-        </p>
+        <div class="row action-header">
+            <div class="col-sm-8">
+                <h1>User Roles</h1>
+            </div>
+            <div class="col-sm-4">
+                <p></p>
+                <a href="/settings/roles/new" class="button float right pos"><i class="zmdi zmdi-lock-open"></i>Add new role</a>
+            </div>
+        </div>
 
         <table class="table">
             <tr>
index f0663071472349fc88ad5ea149ec41419ba2a325..d539f314ee57c49335f67aa09d2149b196145808 100644 (file)
@@ -7,17 +7,42 @@
 
 
     <div class="container small" ng-non-bindable>
-        <h1>Users</h1>
-        @if(userCan('users-manage'))
-            <p>
-                <a href="/settings/users/create" class="text-pos"><i class="zmdi zmdi-account-add"></i>Add new user</a>
-            </p>
-        @endif
+        <div class="row action-header">
+            <div class="col-sm-8">
+                <h1>Users</h1>
+            </div>
+            <div class="col-sm-4">
+                <p></p>
+                @if(userCan('users-manage'))
+                    <a href="/settings/users/create" class="pos button float right"><i class="zmdi zmdi-account-add"></i>Add new user</a>
+                @endif
+            </div>
+        </div>
+
+        <div class="row">
+            <div class="col-sm-8">
+                <div class="compact">
+                    {!! $users->links() !!}
+                </div>
+            </div>
+            <div class="col-sm-4">
+                <form method="get" class="float right" action="/settings/users">
+                    @foreach(collect($listDetails)->except('search') as $name => $val)
+                        <input type="hidden" name="{{$name}}" value="{{$val}}">
+                    @endforeach
+                    <input type="text" name="search" placeholder="Search Users" @if($listDetails['search']) value="{{$listDetails['search']}}" @endif>
+                </form>
+            </div>
+        </div>
+        <div class="text-center">
+
+        </div>
+
         <table class="table">
             <tr>
                 <th></th>
-                <th>Name</th>
-                <th>Email</th>
+                <th><a href="{{ sortUrl('/settings/users', $listDetails, ['sort' => 'name']) }}">Name</a></th>
+                <th><a href="{{ sortUrl('/settings/users', $listDetails, ['sort' => 'email']) }}">Email</a></th>
                 <th>User Roles</th>
             </tr>
             @foreach($users as $user)
                         @endif
                     </td>
                     <td>
-                       <small> {{ $user->roles->implode('display_name', ', ') }}</small>
+                        @foreach($user->roles as $index => $role)
+                            <small><a href="/settings/roles/{{$role->id}}">{{$role->display_name}}</a>@if($index !== count($user->roles) -1),@endif</small>
+                        @endforeach
                     </td>
                 </tr>
             @endforeach
         </table>
+
+        <div>
+            {!! $users->links() !!}
+        </div>
     </div>
 
 @stop