diff --git a/Classes/Controller/BackendController.php b/Classes/Controller/BackendController.php index eef539ba345a612ac0ee36a68c20acde2a5c8bc6..4bad991e7fdd194d90f3c6c8e2420d13480ad670 100644 --- a/Classes/Controller/BackendController.php +++ b/Classes/Controller/BackendController.php @@ -86,70 +86,59 @@ class BackendController extends ActionController { * @return void */ public function indexAction(array $filters = []): void { - try { - $pageUid = (int) GeneralUtility::_GP('id'); - - // create docheader + buttons - $pageInfo = BackendUtility::readPageAccess($pageUid, $GLOBALS['BE_USER']->getPagePermsClause(1)); - if ($pageInfo === FALSE) { - $pageInfo = ['uid' => $pageUid]; - } - - $this->docHeaderComponent = GeneralUtility::makeInstance(DocHeaderComponent::class); - $this->docHeaderComponent->setMetaInformation($pageInfo); - BackendService::makeButtons($this->docHeaderComponent, $this->request); - $this->view->assign('docHeader', $this->docHeaderComponent->docHeaderContent()); - // get all jobs - /** @var ObjectStorage $jobs */ - $jobs = $this->jobRepository->findBackendJobs($pageUid, $filters); - - $totalJobCount = \count($jobs); - - $this->view->assign('pages', BackendService::getPagesWithJobRecords()); - $this->view->assign('pageUid', $pageUid); - - $sortingData = []; - if ($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['sg_jobs']['allowManualSorting'] && count($filters) <= 0) { - - /** - * - * Somehow the pId is changed so data gets lost. - * - * - * $previousUid = 0; - * $sortingData = []; - * foreach ($jobs as $job) { - * if ($previousUid) { - * $sortingData['prev'][$job->getUid()] = $previousUid; - * $sortingData['next'][$previousUid] = $job->getUid(); - * } - * $previousUid = $job->getUid(); - * } - */ - $this->view->assign('manualSortingDestroysEverything', TRUE); - } - - $this->view->assign('sortingData', $sortingData); - - // get all Locations - /** @noinspection PhpUndefinedMethodInspection */ - /** @var QueryResultInterface $companies */ - $companies = $this->companyRepository->findByPid($pageUid); - $this->view->assign('locationOptions', $companies); - if ($totalJobCount || $companies->count()) { - $this->view->assign('jobs', $jobs); - $this->view->assign('filters', $filters); - } else { - $this->view->assign('noRecords', 1); - $this->view->assign('isAdmin', $GLOBALS['BE_USER']->isAdmin()); - $this->addFlashMessage( - LocalizationUtility::translate('backend.notice.noRecords', 'SgJobs'), '', FlashMessage::INFO - ); - } - - } catch (\Exception $exception) { - // check for NULL value in view and render an error message - $this->view->assign('docHeader', NULL); + $pageUid = (int) GeneralUtility::_GP('id'); + + // create docheader + buttons + $pageInfo = BackendUtility::readPageAccess($pageUid, $GLOBALS['BE_USER']->getPagePermsClause(1)); + if ($pageInfo === FALSE) { + $pageInfo = ['uid' => $pageUid]; + } + + $this->docHeaderComponent = GeneralUtility::makeInstance(DocHeaderComponent::class); + $this->docHeaderComponent->setMetaInformation($pageInfo); + BackendService::makeButtons($this->docHeaderComponent, $this->request); + $this->view->assign('docHeader', $this->docHeaderComponent->docHeaderContent()); + + $this->view->assign('pageUid', $pageUid); + $this->view->assign('pages', BackendService::getPagesWithJobRecords()); + + $sortingData = []; + if ($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['sg_jobs']['allowManualSorting'] && count($filters) <= 0) { + /** + * Somehow the pId is changed so data gets lost. + * + * + * $previousUid = 0; + * $sortingData = []; + * foreach ($jobs as $job) { + * if ($previousUid) { + * $sortingData['prev'][$job->getUid()] = $previousUid; + * $sortingData['next'][$previousUid] = $job->getUid(); + * } + * $previousUid = $job->getUid(); + * } + */ + $this->view->assign('manualSortingDestroysEverything', TRUE); + } + $this->view->assign('sortingData', $sortingData); + + /** @var ObjectStorage $jobs */ + $jobs = $this->jobRepository->findBackendJobs($pageUid, $filters); + $totalJobCount = \count($jobs); + + // get all Locations + /** @noinspection PhpUndefinedMethodInspection */ + /** @var QueryResultInterface $companies */ + $companies = $this->companyRepository->findByPid($pageUid); + $this->view->assign('locationOptions', $companies); + + $this->view->assign('isAdmin', $GLOBALS['BE_USER']->isAdmin()); + $this->view->assign('filters', $filters); + $this->view->assign('jobs', $jobs); + if (!$totalJobCount && $pageUid) { + $this->addFlashMessage( + LocalizationUtility::translate('backend.notice.noRecords', 'SgJobs'), '', FlashMessage::INFO + ); } } } diff --git a/Classes/ViewHelpers/Backend/ControlViewHelper.php b/Classes/ViewHelpers/Backend/ControlViewHelper.php index eac8f91167ca96f4ec5f2d4b8bcac9dc80230d16..75b0026a93a93494cf674c238de6ad93c68eb9c8 100644 --- a/Classes/ViewHelpers/Backend/ControlViewHelper.php +++ b/Classes/ViewHelpers/Backend/ControlViewHelper.php @@ -26,6 +26,7 @@ namespace SGalinski\SgJobs\ViewHelpers\Backend; * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ +use SGalinski\SgJobs\Domain\Model\Job; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Page\PageRenderer; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -40,41 +41,31 @@ class ControlViewHelper extends AbstractViewHelper { /** * Initialize the ViewHelper arguments */ - public function initializeArguments() { + public function initializeArguments(): void { parent::initializeArguments(); $this->registerArgument('table', 'string', 'The table to control', TRUE); - $this->registerArgument('row', 'mixed', 'The row of the record', TRUE); - $this->registerArgument('sortingData', 'array', 'The sorting data', FALSE, []); + $this->registerArgument('row', 'object', 'The row of the record', TRUE); } /** * Renders the control buttons for the specified record * * @return string - * @throws \InvalidArgumentException - * @throws \UnexpectedValueException */ public function render(): string { - $row = $this->arguments['row']; $table = $this->arguments['table']; - $sortingData = $this->arguments['sortingData']; + /** @var Job $row */ + $row = $this->arguments['row']; + $row = BackendUtility::getRecord('tx_sgjobs_domain_model_job', $row->getUid()); - /** @var DatabaseRecordList $databaseRecordList */ $databaseRecordList = GeneralUtility::makeInstance(DatabaseRecordList::class); - - if (!\is_array($row)) { - $row = BackendUtility::getRecord($table, $row->getUid()); - } - $pageInfo = BackendUtility::readPageAccess($row['pid'], $GLOBALS['BE_USER']->getPagePermsClause(1)); + $databaseRecordList->calcPerms = $GLOBALS['BE_USER']->calcPerms($pageInfo); $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class); $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/AjaxDataHandler'); $pageRenderer->addInlineLanguageLabelFile('EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf'); $languageService = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Localization\LanguageService::class); $languageService->includeLLFile('EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf'); - $databaseRecordList->calcPerms = $GLOBALS['BE_USER']->calcPerms($pageInfo); - $databaseRecordList->currentTable = $sortingData; return $databaseRecordList->makeControl($table, $row); } - } diff --git a/Classes/ViewHelpers/Backend/IconViewHelper.php b/Classes/ViewHelpers/Backend/IconViewHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..beef6cc6f8245740bfb71c6eb3d21523dbf8caa2 --- /dev/null +++ b/Classes/ViewHelpers/Backend/IconViewHelper.php @@ -0,0 +1,71 @@ +<?php + +namespace SGalinski\SgJobs\ViewHelpers\Backend; + +/*************************************************************** + * Copyright notice + * + * (c) sgalinski Internet Services (https://www.sgalinski.de) + * + * All rights reserved + * + * This script is part of the TYPO3 project. The TYPO3 project 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 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script 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. + * + * This copyright notice MUST APPEAR in all copies of the script! + ***************************************************************/ + +use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Core\Imaging\Icon; +use TYPO3\CMS\Core\Imaging\IconFactory; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; + +/** + * Class EditLink + **/ +class IconViewHelper extends AbstractViewHelper { + /** + * Register the ViewHelper arguments + */ + public function initializeArguments(): void { + parent::initializeArguments(); + $this->registerArgument('table', 'string', 'The table for the icon', TRUE); + $this->registerArgument('row', 'object', 'The row of the record', TRUE); + $this->registerArgument('clickMenu', 'bool', 'Render a clickMenu around the icon', FALSE, TRUE); + } + + /** + * Renders the icon for the specified record + * + * @return string + */ + public function render(): string { + $row = $this->arguments['row']; + $row = BackendUtility::getRecord('tx_sgjobs_domain_model_job', $row->getUid()); + + $table = $this->arguments['table']; + $clickMenu = $this->arguments['clickMenu']; + $iconFactory = GeneralUtility::makeInstance(IconFactory::class); + $toolTip = BackendUtility::getRecordToolTip($row, $table); + $iconImg = '<span ' . $toolTip . '>' + . $iconFactory->getIconForRecord($table, $row, Icon::SIZE_SMALL)->render() + . '</span>'; + if ($clickMenu) { + return BackendUtility::wrapClickMenuOnIcon($iconImg, $table, $row['uid']); + } + return $iconImg; + } + +} diff --git a/Classes/ViewHelpers/Backend/Widget/Controller/PaginateController.php b/Classes/ViewHelpers/Backend/Widget/Controller/PaginateController.php new file mode 100644 index 0000000000000000000000000000000000000000..47265580a5adfcdcb6aeb7e7e530f2825c95898a --- /dev/null +++ b/Classes/ViewHelpers/Backend/Widget/Controller/PaginateController.php @@ -0,0 +1,98 @@ +<?php + +namespace SGalinski\SgJobs\ViewHelpers\Backend\Widget\Controller; + +/*************************************************************** + * Copyright notice + * + * (c) sgalinski Internet Services (https://www.sgalinski.de) + * + * All rights reserved + * + * This script is part of the TYPO3 project. The TYPO3 project 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 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script 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. + * + * This copyright notice MUST APPEAR in all copies of the script! + ***************************************************************/ + +/** + * PaginateController + */ +class PaginateController extends \TYPO3\CMS\Fluid\ViewHelpers\Be\Widget\Controller\PaginateController { + + /** + * @var mixed + */ + protected $objects; + + /** + * Renders the paginator + * + * @param int $currentPage + * @return void + */ + public function indexAction($currentPage = 1) { + // set current page + $this->currentPage = (int) $currentPage; + if ($this->currentPage < 1) { + $this->currentPage = 1; + } + + if ($this->currentPage > $this->numberOfPages) { + // set $modifiedObjects to NULL if the page does not exist + $modifiedObjects = NULL; + } else { + // modify query + $this->itemsPerPage = (int) $this->configuration['itemsPerPage']; + $this->offset = $this->itemsPerPage * ($this->currentPage - 1); + if (\is_array($this->objects)) { + $modifiedObjects = []; + for ($index = $this->offset; $index < $this->offset + $this->itemsPerPage; $index++) { + if (isset($this->objects[$index])) { + $modifiedObjects[] = $this->objects[$index]; + } else { + break; + } + } + } else { + $query = $this->objects->getQuery(); + $query->setLimit($this->itemsPerPage); + if ($this->currentPage > 1) { + $query->setOffset($this->offset); + } + + $modifiedObjects = $query->execute(); + } + } + $this->view->assign( + 'contentArguments', [ + $this->widgetConfiguration['as'] => $modifiedObjects + ] + ); + $this->view->assign('configuration', $this->configuration); + $this->view->assign('pagination', $this->buildPagination()); + } + + /** + * Returns an array with the keys "pages", "current", "numberOfPages", + * "nextPage" & "previousPage" + * + * @return array + */ + protected function buildPagination() { + $pagination = parent::buildPagination(); + $pagination['totalObjects'] = \count($this->objects); + return $pagination; + } +} diff --git a/Classes/ViewHelpers/Backend/Widget/PaginateViewHelper.php b/Classes/ViewHelpers/Backend/Widget/PaginateViewHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..db62e1b0da75dfedd58b013bff8e0c850898b89c --- /dev/null +++ b/Classes/ViewHelpers/Backend/Widget/PaginateViewHelper.php @@ -0,0 +1,81 @@ +<?php + +namespace SGalinski\SgJobs\ViewHelpers\Backend\Widget; + +/*************************************************************** + * Copyright notice + * + * (c) sgalinski Internet Services (https://www.sgalinski.de) + * + * All rights reserved + * + * This script is part of the TYPO3 project. The TYPO3 project 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 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script 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. + * + * This copyright notice MUST APPEAR in all copies of the script! + ***************************************************************/ + +use SGalinski\SgJobs\ViewHelpers\Backend\Widget\Controller\PaginateController; +use TYPO3\CMS\Fluid\Core\Widget\AbstractWidgetViewHelper; + +/** + * Class PaginateViewHelper + * + * @package SGalinski\SgJobs\ViewHelpers\Backend\Widget + */ +class PaginateViewHelper extends AbstractWidgetViewHelper { + /** + * @var PaginateController + */ + protected $controller; + + /** + * Initializes the controller + * + * @param PaginateController $controller + */ + public function injectPaginateController(PaginateController $controller): void { + $this->controller = $controller; + } + + /** + * Register the ViewHelper arguments + */ + public function initializeArguments(): void { + parent::initializeArguments(); + $this->registerArgument('objects', 'array', 'The objects to paginate', TRUE); + $this->registerArgument('as', 'string', 'The name of the variable inside the pagination', TRUE); + $this->registerArgument( + 'configuration', + 'array', + 'The configuration of the pagination', + FALSE, + [ + 'itemsPerPage' => 10, + 'insertAbove' => FALSE, + 'insertBelow' => TRUE, + 'recordsLabel' => '' + ] + ); + } + + /** + * Renders the paginator + * + * @return string + */ + public function render(): string { + return $this->initiateSubRequest(); + } +} diff --git a/Classes/ViewHelpers/Widget/UriViewHelper.php b/Classes/ViewHelpers/Widget/UriViewHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..e33ba7e35f1bbc69613fefa7a321f4bc15d2760d --- /dev/null +++ b/Classes/ViewHelpers/Widget/UriViewHelper.php @@ -0,0 +1,157 @@ +<?php + +namespace SGalinski\SgJobs\ViewHelpers\Widget; + +/*************************************************************** + * Copyright notice + * + * (c) sgalinski Internet Services (https://www.sgalinski.de) + * + * All rights reserved + * + * This script is part of the TYPO3 project. The TYPO3 project 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 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script 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. + * + * This copyright notice MUST APPEAR in all copies of the script! + ***************************************************************/ + +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext; +use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; +use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; +use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic; + +/** + * Class UriViewHelper + */ +class UriViewHelper extends AbstractViewHelper { + + use CompileWithRenderStatic; + + /** + * @var boolean + */ + protected $escapeOutput = FALSE; + + /** + * @var boolean + */ + protected $escapeChildren = FALSE; + + /** + * Initialize arguments + */ + public function initializeArguments(): void { + $this->registerArgument('addQueryStringMethod', 'string', 'Method to be used for query string'); + $this->registerArgument('action', 'string', 'Target action'); + $this->registerArgument('arguments', 'array', 'Arguments', FALSE, []); + $this->registerArgument('section', 'string', 'The anchor to be added to the URI', FALSE, ''); + $this->registerArgument('format', 'string', 'The requested format, e.g. ".html', FALSE, ''); + $this->registerArgument( + 'ajax', 'bool', 'TRUE if the URI should be to an AJAX widget, FALSE otherwise.', FALSE, FALSE + ); + } + + /** + * @param array $arguments + * @param \Closure $renderChildrenClosure + * @param RenderingContextInterface $renderingContext + * @return string + */ + public static function renderStatic( + array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext + ): string { + $ajax = $arguments['ajax']; + if ($ajax === TRUE) { + return static::getAjaxUri($renderingContext, $arguments); + } + return static::getWidgetUri($renderingContext, $arguments); + } + + /** + * Render the Uri. + * + * @return string The rendered link + * @api + */ + public function render(): string { + $ajax = $this->arguments['ajax']; + + if ($ajax === TRUE) { + return static::getAjaxUri($this->renderingContext, $this->arguments); + } + return static::getWidgetUri($this->renderingContext, $this->arguments); + } + + /** + * Get the URI for an AJAX Request. + * + * @param RenderingContextInterface $renderingContext + * @param array $arguments + * @return string the AJAX URI + */ + protected static function getAjaxUri(RenderingContextInterface $renderingContext, array $arguments): string { + /** @var ControllerContext $controllerContext */ + $controllerContext = $renderingContext->getControllerContext(); + $action = $arguments['action']; + $arguments = $arguments['arguments']; + if ($action === NULL) { + $action = $controllerContext->getRequest()->getControllerActionName(); + } + + $arguments['id'] = $GLOBALS['TSFE']->id; + // @todo page type should be configurable + $arguments['type'] = 7076; + $arguments['fluid-widget-id'] = $controllerContext->getRequest()->getWidgetContext()->getAjaxWidgetIdentifier(); + $arguments['action'] = $action; + return '?' . http_build_query($arguments, NULL, '&'); + } + + /** + * Get the URI for a non-AJAX Request. + * + * @param RenderingContextInterface $renderingContext + * @param array $arguments + * @return string the Widget URI + */ + protected static function getWidgetUri(RenderingContextInterface $renderingContext, array $arguments): string { + /** @var ControllerContext $controllerContext */ + $controllerContext = $renderingContext->getControllerContext(); + $uriBuilder = $controllerContext->getUriBuilder(); + $argumentPrefix = $controllerContext->getRequest()->getArgumentPrefix(); + $parentNamespace = $controllerContext->getRequest()->getWidgetContext()->getParentPluginNamespace(); + $parentArguments = GeneralUtility::_GP($parentNamespace); + $allArguments = [$argumentPrefix => $arguments['arguments']] ?? []; + if ($parentArguments && isset($parentArguments['filters'])) { + $allArguments[$parentNamespace . '[filters]'] = $parentArguments['filters']; + } + + if ($arguments['action'] ?? FALSE) { + $allArguments[$argumentPrefix]['action'] = $arguments['action']; + } + + if (($arguments['format'] ?? '') !== '') { + $allArguments[$argumentPrefix]['format'] = $arguments['format']; + } + + return $uriBuilder->reset() + ->setArguments($allArguments) + ->setSection($arguments['section']) + ->setAddQueryString(TRUE) + ->setAddQueryStringMethod($arguments['addQueryStringMethod'] ?? '') + ->setArgumentsToBeExcludedFromQueryString([$argumentPrefix, 'cHash']) + ->setFormat($arguments['format']) + ->build(); + } +} diff --git a/Resources/Private/Backend/Layouts/Default.html b/Resources/Private/Backend/Layouts/Default.html index b9a09ad482f184bc13c629ce4e537693833b5d33..fa390fae138239dca41e2ef3741dc94728f5e2aa 100644 --- a/Resources/Private/Backend/Layouts/Default.html +++ b/Resources/Private/Backend/Layouts/Default.html @@ -35,7 +35,7 @@ <h1> <f:render section="headline" /> </h1> - <f:render section="content" /> + <f:render section="main" /> </div> </div> </f:be.container> diff --git a/Resources/Private/Backend/Partials/JobList.html b/Resources/Private/Backend/Partials/JobList.html deleted file mode 100644 index ccaf4f273e7eaa15cff745053578b0ff6b0b6bca..0000000000000000000000000000000000000000 --- a/Resources/Private/Backend/Partials/JobList.html +++ /dev/null @@ -1,36 +0,0 @@ -{namespace sg=SGalinski\SgJobs\ViewHelpers} -{namespace be=TYPO3\CMS\Backend\ViewHelpers} - -<p> - <f:translate key="backend.message.sorting" /> -</p> - -<f:if condition="{manualSortingDestroysEverything}"> - <h2><f:translate key="backend.manualSortingBug" /></h2> -</f:if> - -<div class="panel panel-default recordlist"> - <div class="table-fit"> - <f:be.widget.paginate objects="{jobs}" as="paginatedJobs" configuration="{insertAbove: 1, itemsPerPage: 20}"> - <table data-table="tx_sgjobs_domain_model_job" class="table table-striped table-hover"> - <tbody> - <f:for each="{paginatedJobs}" as="job"> - <tr data-uid="{job.uid}"> - <td nowrap="nowrap" class="col-icon"> - <core:icon identifier="tcarecords-tx_sgjobs_domain_model_job-default"></core:icon> - </td> - <td style="white-space: normal;"> - <be:link.editRecord uid="{job.uid}" table="tx_sgjobs_domain_model_job"> - <span>{job.title} - {job.company.name}, {job.company.city}</span> - </be:link.editRecord> - </td> - <td nowrap="nowrap" class="col-control"> - <f:format.raw><sg:backend.control table="tx_sgjobs_domain_model_job" row="{job}" sortingData="{sortingData}"/></f:format.raw> - </td> - </tr> - </f:for> - </tbody> - </table> - </f:be.widget.paginate> - </div> -</div> diff --git a/Resources/Private/Backend/Templates/Index.html b/Resources/Private/Backend/Templates/Index.html index fbfb7918a15413ca552e8c4e0d98423ac4ce4cf1..55343fa2927644a8108ec91b55cfa5e41671307b 100644 --- a/Resources/Private/Backend/Templates/Index.html +++ b/Resources/Private/Backend/Templates/Index.html @@ -1,62 +1,63 @@ {namespace sg=SGalinski\SgJobs\ViewHelpers} +{namespace be=TYPO3\CMS\Backend\ViewHelpers} -<f:layout name="Default" /> +<f:layout name="Default"/> <f:section name="iconButtons"> </f:section> <f:section name="headline"> - <f:translate key="backend.jobs.header" /> + <f:translate key="backend.jobs.header"/> </f:section> -<f:section name="content"> + +<f:section name="main"> <f:flashMessages /> - <f:if condition="{pageUid}"> + <f:if condition="{jobs}"> <f:then> - <f:if condition="{docHeader}"> - <f:then> - <f:if condition="{noRecords}"> - <f:then> - <f:if condition="{locationOptions}"> - <f:then> - <f:render partial="Filter" arguments="{filters: filters, locationOptions: locationOptions}" /> - <f:render partial="CreateJob" arguments="{pageUid:pageUid}" /> - <p> - <f:translate key="backend.noJobsMessage" /> - </p> - </f:then> - <f:else> - <f:render partial="SelectRoot" arguments="{pages: pages}" /> - <f:render partial="CreateJob" arguments="{pageUid:pageUid}" /> - </f:else> - </f:if> - </f:then> - <f:else> - <f:render partial="Filter" arguments="{filters: filters, locationOptions: locationOptions}" /> - <f:render partial="CreateJob" arguments="{pageUid:pageUid}" /> - <f:if condition="{jobs}"> - <f:then> - <f:render partial="JobList" arguments="{jobs: jobs, manualSortingDestroysEverything: manualSortingDestroysEverything}" /> - </f:then> - <f:else> - <p> - <f:translate key="backend.noJobsMessage" /> - </p> - </f:else> - </f:if> - </f:else> - </f:if> - </f:then> - <f:else> - <f:render partial="Error" /> - </f:else> + <f:render partial="Filter" arguments="{_all}"/> + <f:render partial="CreateJob" arguments="{_all}"/> + + <p> + <f:translate key="backend.message.sorting"/> + </p> + + <f:if condition="{manualSortingDestroysEverything}"> + <h2> + <f:translate key="backend.manualSortingBug"/> + </h2> </f:if> + + <div class="panel panel-default recordlist"> + <div class="table-fit"> + <table data-table="tx_sgjobs_domain_model_job" class="table table-striped table-hover"> + <sg:backend.widget.paginate objects="{jobs}" as="paginatedJobs" configuration="{insertAbove: 1, itemsPerPage: 20}"> + <tbody> + <f:for each="{paginatedJobs}" as="job"> + <tr data-uid="{job.uid}"> + <td nowrap="nowrap" class="col-icon"> + <f:format.raw><sg:backend.icon table="tx_sgjobs_domain_model_job" row="{job}" /></f:format.raw> + </td> + <td style="white-space: normal;"> + <be:link.editRecord uid="{job.uid}" table="tx_sgjobs_domain_model_job"> + <span>{job.title} - {job.company.name}, {job.company.city}</span> + </be:link.editRecord> + </td> + <td nowrap="nowrap" class="col-control"> + <f:format.raw><sg:backend.control table="tx_sgjobs_domain_model_job" row="{job}" /></f:format.raw> + </td> + </tr> + </f:for> + </tbody> + </sg:backend.widget.paginate> + </table> + </div> + </div> </f:then> <f:else> - <f:render partial="SelectRoot" arguments="{pages: pages}" /> + <f:render partial="SelectRoot" arguments="{pages: pages}"/> <f:if condition="{isAdmin}"> - <f:render partial="CreateJob" arguments="{pageUid:pageUid}" /> + <f:render partial="CreateJob" arguments="{pageUid:pageUid}"/> </f:if> </f:else> </f:if> - </f:section> diff --git a/Resources/Private/Backend/Templates/ViewHelpers/Backend/Widget/Paginate/Index.html b/Resources/Private/Backend/Templates/ViewHelpers/Backend/Widget/Paginate/Index.html new file mode 100644 index 0000000000000000000000000000000000000000..1dd3b4ac4a673bc9fbd2f99fb6e825c2f62e8039 --- /dev/null +++ b/Resources/Private/Backend/Templates/ViewHelpers/Backend/Widget/Paginate/Index.html @@ -0,0 +1,125 @@ +{namespace core=TYPO3\CMS\Core\ViewHelpers} +{namespace sg=SGalinski\SgJobs\ViewHelpers} + +<f:if condition="{configuration.insertAbove}"> + <thead> + <tr> + <td colspan="3"> + <f:render section="paginator" arguments="{pagination: pagination, position:'top', recordsLabel: configuration.recordsLabel}" /> + </td> + </tr> + </thead> +</f:if> + +<f:renderChildren arguments="{contentArguments}" /> + +<f:if condition="{configuration.insertBelow}"> + <tfoot> + <tr> + <td colspan="3"> + <f:render section="paginator" arguments="{pagination: pagination, position:'bottom', recordsLabel: configuration.recordsLabel}" /> + </td> + </tr> + </tfoot> +</f:if> + +<f:section name="paginator"> + <nav class="pagination-wrap"> + <ul class="pagination pagination-block"> + <f:if condition="{pagination.hasLessPages}"> + <f:then> + <li> + <a href="{sg:widget.uri(arguments:{currentPage: 1})}" title="{f:translate(key:'widget.pagination.first')}"> + <core:icon identifier="actions-view-paging-first" /> + </a> + </li> + <li> + <a href="{sg:widget.uri(arguments:{currentPage: pagination.previousPage})}" title="{f:translate(key:'widget.pagination.previous')}"> + <core:icon identifier="actions-view-paging-previous" /> + </a> + </li> + </f:then> + <f:else> + <li class="disabled"> + <span> + <core:icon identifier="actions-view-paging-first" /> + </span> + </li> + <li class="disabled"> + <span> + <core:icon identifier="actions-view-paging-previous" /> + </span> + </li> + </f:else> + </f:if> + <li> + <span> + <f:if condition="{recordsLabel}"> + <f:then> + {recordsLabel} + </f:then> + <f:else> + <f:translate key="widget.pagination.records" /> + </f:else> + </f:if> + {pagination.startRecord} - {pagination.endRecord} / {pagination.totalObjects} + </span> + </li> + <li> + <span> + <f:translate key="widget.pagination.page" /> + + <form id="paginator-form-{position}" onsubmit="goToPage{position}(this); return false;" style="display:inline;"> + <script type="text/javascript"> + function goToPage{position}(formObject) { + var url = '{sg:widget.uri(arguments:{currentPage: 987654321}) -> f:format.raw()}'; + var page = formObject.elements['paginator-target-page'].value; + if (page > {pagination.numberOfPages}) { + page = {pagination.numberOfPages}; + } else if (page < 1) { + page = 1; + } + url = url.replace('987654321', page); + self.location.href= url; + } + </script> + <f:form.textfield id="paginator-{position}" name="paginator-target-page" additionalAttributes="{min: '1'}" class="form-control input-sm paginator-input" size="5" value="{pagination.current}" type="number" /> + </form> + + / {pagination.numberOfPages} + </span> + </li> + <f:if condition="{pagination.hasMorePages}"> + <f:then> + <li> + <a href="{sg:widget.uri(arguments:{currentPage: pagination.nextPage})}" title="{f:translate(key:'widget.pagination.next')}"> + <core:icon identifier="actions-view-paging-next" /> + </a> + </li> + <li> + <a href="{sg:widget.uri(arguments:{currentPage: pagination.numberOfPages})}" title="{f:translate(key:'widget.pagination.last')}"> + <core:icon identifier="actions-view-paging-last" /> + </a> + </li> + </f:then> + <f:else> + <li class="disabled"> + <span> + <core:icon identifier="actions-view-paging-next" /> + </span> + </li> + <li class="disabled"> + <span> + <core:icon identifier="actions-view-paging-last" /> + </span> + </li> + </f:else> + </f:if> + <li> + <a href="{sg:widget.uri(arguments:{currentPage: pagination.current})}" title="{f:translate(key:'widget.pagination.refresh')}"> + <core:icon identifier="actions-refresh" /> + </a> + </li> + </ul> + </nav> +</f:section>