Skip to content

Commit

Permalink
[FEATURE] Introduce support for pagination on job list page
Browse files Browse the repository at this point in the history
  • Loading branch information
eliashaeussler committed Mar 15, 2024
1 parent 0a96dab commit eef856c
Show file tree
Hide file tree
Showing 15 changed files with 400 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/cgl.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
# Install dependencies
- name: Install Composer dependencies
run: |
composer require --no-progress --no-plugins brotkrueml/schema:"^2.7 || ^3.0"
composer require --no-progress --no-plugins brotkrueml/schema:"^2.7 || ^3.0" georgringer/numbered-pagination:"^1.0 || ^2.0"
# Check Composer dependencies
- name: Check dependencies
Expand Down
46 changes: 45 additions & 1 deletion Classes/Controller/JobController.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,16 @@
use CPSIT\Typo3PersonioJobs\Domain\Repository\JobRepository;
use CPSIT\Typo3PersonioJobs\Exception\ExtensionNotLoadedException;
use CPSIT\Typo3PersonioJobs\PageTitle\JobPageTitleProvider;
use CPSIT\Typo3PersonioJobs\Pagination\PaginationFactory;
use CPSIT\Typo3PersonioJobs\Service\PersonioApiService;
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Core\MetaTag\MetaTagManagerRegistry;
use TYPO3\CMS\Core\Pagination\PaginationInterface;
use TYPO3\CMS\Core\Pagination\PaginatorInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use TYPO3\CMS\Extbase\Pagination\QueryResultPaginator;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;

/**
* JobController
Expand All @@ -52,16 +57,30 @@ public function __construct(
protected readonly CacheManager $cacheManager,
protected readonly PersonioApiService $personioApiService,
protected readonly SchemaFactory $schemaFactory,
protected readonly PaginationFactory $paginationFactory,
) {}

public function listAction(): ResponseInterface
{
$this->cacheManager->addTag();

// Fetch jobs
$demand = ListDemand::fromArray($this->settings);
$jobs = $this->jobRepository->findByDemand($demand);

$this->view->assign('jobs', $jobs);
// Create pagination
if ($this->settings['enablePagination'] ?? false) {
[$paginator, $pagination] = $this->createPagination($jobs);
} else {
$paginator = null;
$pagination = null;
}

$this->view->assignMultiple([
'jobs' => $jobs,
'paginator' => $paginator,
'pagination' => $pagination,
]);

return $this->htmlResponse();
}
Expand Down Expand Up @@ -137,4 +156,29 @@ protected function addSchema(Job $job): void
$schemaManager = GeneralUtility::makeInstance(SchemaManager::class);
$schemaManager->addType($jobPosting);
}

/**
* @param QueryResultInterface<Job> $jobs
* @return array{PaginatorInterface, PaginationInterface}
*/
private function createPagination(QueryResultInterface $jobs): array
{
$itemsPerPage = (int)($this->settings['itemsPerPage'] ?? 10);
$maximumNumberOfLinks = (int)($this->settings['maximumNumberOfLinks'] ?? 5);
$currentPageNumber = 1;

// Get current page number from request
if ($this->request->hasArgument('currentPage')) {
$currentPageFromRequest = $this->request->getArgument('currentPage');

if (is_numeric($currentPageFromRequest) && $currentPageFromRequest >= 1) {
$currentPageNumber = (int)$currentPageFromRequest;
}
}

$paginator = new QueryResultPaginator($jobs, $currentPageNumber, $itemsPerPage);
$pagination = $this->paginationFactory->get($paginator, $maximumNumberOfLinks);

return [$paginator, $pagination];
}
}
53 changes: 53 additions & 0 deletions Classes/Pagination/PaginationFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

declare(strict_types=1);

/*
* This file is part of the TYPO3 CMS extension "personio_jobs".
*
* Copyright (C) 2023 Elias Häußler <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

namespace CPSIT\Typo3PersonioJobs\Pagination;

use GeorgRinger\NumberedPagination\NumberedPagination;
use TYPO3\CMS\Core\Pagination\PaginationInterface;
use TYPO3\CMS\Core\Pagination\PaginatorInterface;
use TYPO3\CMS\Core\Pagination\SimplePagination;
use TYPO3\CMS\Core\Pagination\SlidingWindowPagination;
use TYPO3\CMS\Core\Utility\GeneralUtility;

/**
* PaginationFactory
*
* @author Elias Häußler <[email protected]>
* @license GPL-2.0-or-later
*/
final class PaginationFactory
{
public function get(PaginatorInterface $paginator, int $maximumNumberOfLinks = 5): PaginationInterface
{
if (class_exists(NumberedPagination::class)) {
return GeneralUtility::makeInstance(NumberedPagination::class, $paginator, $maximumNumberOfLinks);
}

if (class_exists(SlidingWindowPagination::class)) {
return new SlidingWindowPagination($paginator, $maximumNumberOfLinks);
}

return new SimplePagination($paginator);
}
}
38 changes: 38 additions & 0 deletions Configuration/FlexForms/List.v11.xml
Original file line number Diff line number Diff line change
Expand Up @@ -100,5 +100,43 @@
</el>
</ROOT>
</filter>
<pagination>
<ROOT>
<TCEforms>
<sheetTitle>LLL:EXT:personio_jobs/Resources/Private/Language/locallang_be.xlf:flexforms.tab.pagination</sheetTitle>
</TCEforms>
<type>array</type>
<el>
<settings.enablePagination>
<TCEforms>
<label>LLL:EXT:personio_jobs/Resources/Private/Language/locallang_be.xlf:flexforms.list.settings.enablePagination</label>
<config>
<type>check</type>
</config>
</TCEforms>
</settings.enablePagination>
<settings.itemsPerPage>
<TCEforms>
<label>LLL:EXT:personio_jobs/Resources/Private/Language/locallang_be.xlf:flexforms.list.settings.itemsPerPage</label>
<config>
<type>input</type>
<eval>trim,int</eval>
<default>10</default>
</config>
</TCEforms>
</settings.itemsPerPage>
<settings.maximumNumberOfLinks>
<TCEforms>
<label>LLL:EXT:personio_jobs/Resources/Private/Language/locallang_be.xlf:flexforms.list.settings.maximumNumberOfLinks</label>
<config>
<type>input</type>
<eval>trim,int</eval>
<default>5</default>
</config>
</TCEforms>
</settings.maximumNumberOfLinks>
</el>
</ROOT>
</pagination>
</sheets>
</T3DataStructure>
28 changes: 28 additions & 0 deletions Configuration/FlexForms/List.xml
Original file line number Diff line number Diff line change
Expand Up @@ -84,5 +84,33 @@
</el>
</ROOT>
</filter>
<pagination>
<ROOT>
<sheetTitle>LLL:EXT:personio_jobs/Resources/Private/Language/locallang_be.xlf:flexforms.tab.pagination</sheetTitle>
<type>array</type>
<el>
<settings.enablePagination>
<label>LLL:EXT:personio_jobs/Resources/Private/Language/locallang_be.xlf:flexforms.list.settings.enablePagination</label>
<config>
<type>check</type>
</config>
</settings.enablePagination>
<settings.itemsPerPage>
<label>LLL:EXT:personio_jobs/Resources/Private/Language/locallang_be.xlf:flexforms.list.settings.itemsPerPage</label>
<config>
<type>number</type>
<default>10</default>
</config>
</settings.itemsPerPage>
<settings.maximumNumberOfLinks>
<label>LLL:EXT:personio_jobs/Resources/Private/Language/locallang_be.xlf:flexforms.list.settings.maximumNumberOfLinks</label>
<config>
<type>number</type>
<default>5</default>
</config>
</settings.maximumNumberOfLinks>
</el>
</ROOT>
</pagination>
</sheets>
</T3DataStructure>
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ with preconfigured support for Bootstrap v5 components.
* Usage of modern-typed value objects during the import process
* Plugins for list and detail view
* Optional support for JSON Schema on job detail pages using [EXT:schema][1]
* Optional support for pagination using [EXT:numbered_pagination][5]
* Compatible with TYPO3 11.5 LTS, 12.4 LTS and 13.0

## 🔥 Installation
Expand All @@ -51,6 +52,13 @@ additionally require the `schema` extension:
composer require brotkrueml/schema
```

💡 If you want to enable pagination on job list pages, it is suggested
to additionally require the `numbered_pagination` extension:

```bash
composer require georgringer/numbered-pagination
```

### TER

Alternatively, you can download the extension via the
Expand Down Expand Up @@ -276,3 +284,4 @@ This project is licensed under [GNU General Public License 2.0 (or later)](LICEN
[2]: https://extensions.typo3.org/extension/personio_jobs
[3]: https://schema.org/JobPosting
[4]: https://www.personio.de/
[5]: https://extensions.typo3.org/extension/numbered_pagination
10 changes: 10 additions & 0 deletions Resources/Private/Language/locallang.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@
<trans-unit id="link.apply">
<source>Apply now</source>
</trans-unit>

<trans-unit id="pagination.ariaLabel">
<source>Job list pagination</source>
</trans-unit>
<trans-unit id="pagination.previous">
<source>Previous</source>
</trans-unit>
<trans-unit id="pagination.next">
<source>Next</source>
</trans-unit>
</body>
</file>
</xliff>
12 changes: 12 additions & 0 deletions Resources/Private/Language/locallang_be.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
<trans-unit id="flexforms.tab.filter">
<source>Filter</source>
</trans-unit>
<trans-unit id="flexforms.tab.pagination">
<source>Pagination</source>
</trans-unit>

<trans-unit id="flexforms.show.settings.listPid">
<source>List page</source>
Expand Down Expand Up @@ -63,6 +66,15 @@
<trans-unit id="flexforms.list.settings.filter.subcompanyExclude.description">
<source>Multiple values can be separated by comma.</source>
</trans-unit>
<trans-unit id="flexforms.list.settings.enablePagination">
<source>Enable pagination</source>
</trans-unit>
<trans-unit id="flexforms.list.settings.itemsPerPage">
<source>Items per page</source>
</trans-unit>
<trans-unit id="flexforms.list.settings.maximumNumberOfLinks">
<source>Maximum number of links</source>
</trans-unit>
</body>
</file>
</xliff>
73 changes: 73 additions & 0 deletions Resources/Private/Partials/List/Pagination.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
data-namespace-typo3-fluid="true">

<nav aria-label="{f:translate(key: 'pagination.ariaLabel')}">
<ul class="pagination justify-content-center mt-3">
<f:comment><!-- Previous/First page --></f:comment>
<f:if condition="{paginator.currentPageNumber} > {pagination.firstPageNumber}">
<f:then>
<f:render partial="List/Pagination/PageLink" arguments="{
actionName: actionName,
page: pagination.previousPageNumber,
label: '{f:translate(key: \'pagination.previous\')}'
}" />

<f:if condition="{pagination.displayRangeStart} > {pagination.firstPageNumber}">
<f:render partial="List/Pagination/PageLink" arguments="{
actionName: actionName,
page: pagination.firstPageNumber
}" />
</f:if>
</f:then>
<f:else>
<f:render partial="List/Pagination/Disabled" arguments="{
label: '{f:translate(key: \'pagination.previous\')}'
}" />
</f:else>
</f:if>

<f:comment><!-- Placeholder --></f:comment>
<f:if condition="{pagination.hasLessPages} && {pagination.displayRangeStart - 1} > {pagination.firstPageNumber}">
<f:render partial="List/Pagination/Placeholder" />
</f:if>

<f:comment><!-- All pages --></f:comment>
<f:for each="{pagination.allPageNumbers}" as="page">
<f:render partial="List/Pagination/PageLink" arguments="{
actionName: actionName,
page: page,
active: '{f:if(condition: \'{page} == {paginator.currentPageNumber}\', then: 1)}'
}" />
</f:for>

<f:comment><!-- Placeholder --></f:comment>
<f:if condition="{pagination.hasMorePages} && {pagination.displayRangeEnd + 1} < {pagination.lastPageNumber}">
<f:render partial="List/Pagination/Placeholder" />
</f:if>

<f:comment><!-- Last/Next page --></f:comment>
<f:if condition="{paginator.currentPageNumber} < {pagination.lastPageNumber}">
<f:then>
<f:if condition="{pagination.displayRangeEnd} < {pagination.lastPageNumber}">
<f:render partial="List/Pagination/PageLink" arguments="{
actionName: actionName,
page: pagination.lastPageNumber
}" />
</f:if>

<f:render partial="List/Pagination/PageLink" arguments="{
actionName: actionName,
page: pagination.nextPageNumber,
label: '{f:translate(key: \'pagination.next\')}'
}" />
</f:then>
<f:else>
<f:render partial="List/Pagination/Disabled" arguments="{
label: '{f:translate(key: \'pagination.next\')}'
}" />
</f:else>
</f:if>
</ul>
</nav>

</html>
8 changes: 8 additions & 0 deletions Resources/Private/Partials/List/Pagination/Disabled.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
data-namespace-typo3-fluid="true">

<li class="page-item disabled">
<a class="page-link">{label}</a>
</li>

</html>
23 changes: 23 additions & 0 deletions Resources/Private/Partials/List/Pagination/PageLink.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
data-namespace-typo3-fluid="true">

<f:if condition="{active}">
<f:then>
<li class="page-item active" aria-current="page">
<f:link.action action="{actionName}"
arguments="{currentPage: page}"
class="page-link"
>{f:if(condition: label, then: label, else: page)}</f:link.action>
</li>
</f:then>
<f:else>
<li class="page-item">
<f:link.action action="{actionName}"
arguments="{currentPage: page}"
class="page-link"
>{f:if(condition: label, then: label, else: page)}</f:link.action>
</li>
</f:else>
</f:if>

</html>
Loading

0 comments on commit eef856c

Please sign in to comment.