Implement simple pagination

This commit is contained in:
Ahmed Ashraf
2020-06-26 12:20:01 +02:00
parent baa9819daf
commit e960ffb825
5 changed files with 74 additions and 7 deletions

View File

@@ -10,6 +10,8 @@ interface UserRepository
public function getUserById($id): PromiseInterface; public function getUserById($id): PromiseInterface;
public function paginateUsers(int $perPage, int $currentPage): PromiseInterface;
public function getUserByToken(string $authToken): PromiseInterface; public function getUserByToken(string $authToken): PromiseInterface;
public function storeUser(array $data): PromiseInterface; public function storeUser(array $data): PromiseInterface;

View File

@@ -21,10 +21,10 @@ class GetUsersController extends AdminController
public function handle(Request $request, ConnectionInterface $httpConnection) public function handle(Request $request, ConnectionInterface $httpConnection)
{ {
$this->userRepository $this->userRepository
->getUsers() ->paginateUsers(20, (int) $request->get('page', 1))
->then(function ($users) use ($httpConnection) { ->then(function ($paginated) use ($httpConnection) {
$httpConnection->send( $httpConnection->send(
respond_json(['users' => $users]) respond_json(['paginated' => $paginated])
); );
$httpConnection->close(); $httpConnection->close();

View File

@@ -21,10 +21,10 @@ class ListUsersController extends AdminController
public function handle(Request $request, ConnectionInterface $httpConnection) public function handle(Request $request, ConnectionInterface $httpConnection)
{ {
$this->userRepository $this->userRepository
->getUsers() ->paginateUsers(20, (int) $request->get('page', 1))
->then(function ($users) use ($httpConnection) { ->then(function ($paginated) use ($httpConnection) {
$httpConnection->send( $httpConnection->send(
respond_html($this->getView($httpConnection, 'server.users.index', ['users' => $users])) respond_html($this->getView($httpConnection, 'server.users.index', ['paginated' => $paginated]))
); );
$httpConnection->close(); $httpConnection->close();

View File

@@ -31,6 +31,35 @@ class DatabaseUserRepository implements UserRepository
return $deferred->promise(); return $deferred->promise();
} }
public function paginateUsers(int $perPage, int $currentPage): PromiseInterface
{
$deferred = new Deferred();
$this->database
->query('SELECT * FROM users ORDER by created_at DESC LIMIT :limit OFFSET :offset', [
'limit' => $perPage + 1,
'offset' => $currentPage < 2 ? 0 : ($currentPage - 1) * $perPage,
])
->then(function (Result $result) use ($deferred, $perPage, $currentPage) {
if(count($result->rows) == $perPage + 1) {
array_pop($result->rows);
$nextPage = $currentPage + 1;
}
$paginated = [
'users' => $result->rows,
'current_page' => $currentPage,
'per_page' => $perPage,
'next_page' => $nextPage ?? null,
'previous_page' => $currentPage > 1 ? $currentPage - 1 : null,
];
$deferred->resolve($paginated);
});
return $deferred->promise();
}
public function getUserById($id): PromiseInterface public function getUserById($id): PromiseInterface
{ {
$deferred = new Deferred(); $deferred = new Deferred();

View File

@@ -75,6 +75,27 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<div class="flex items-center justify-end text-gray-900 p-4" v-if="paginated.current_page > 0">
<button
:disabled="paginated.previous_page == null"
v-on:click="getUsers(paginated.previous_page)"
type="button"
:class="(paginated.previous_page == null ? 'opacity-50 cursor-not-allowed' : '') + ' mr-3 py-2 px-4 border border-gray-300 rounded-md text-sm leading-5 font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:bg-gray-50 active:text-gray-800 transition duration-150 ease-in-out'"
>
Previous
</button>
<button
:disabled="paginated.next_page == null"
v-on:click="getUsers(paginated.next_page)"
type="button"
:class="(paginated.next_page == null ? 'opacity-50 cursor-not-allowed' : '') + ' py-2 px-4 border border-gray-300 rounded-md text-sm leading-5 font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:bg-gray-50 active:text-gray-800 transition duration-150 ease-in-out'"
>
Next
</button>
</div>
<div class="flex items-center justify-center text-gray-900 p-4" v-else> <div class="flex items-center justify-center text-gray-900 p-4" v-else>
<span class="text-xl">The expose server does not have any users yet.</span> <span class="text-xl">The expose server does not have any users yet.</span>
</div> </div>
@@ -94,10 +115,25 @@
name: '', name: '',
errors: {}, errors: {},
}, },
users: {{ users|json_encode|raw }} paginated: {{ paginated|json_encode|raw }}
},
computed: {
users : function() {
return this.paginated.users;
}
}, },
methods: { methods: {
getUsers(page) {
fetch('/api/users?page=' + page)
.then((response) => {
return response.json();
}).then((data) => {
this.paginated = data.paginated;
});
},
deleteUser(user) { deleteUser(user) {
fetch('/api/users/' + user.id, { fetch('/api/users/' + user.id, {
method: 'DELETE', method: 'DELETE',