fab / vidi-frontend
前端通用列表组件,可以以高级方式过滤内容... 来了,看到了,征服了!
Requires
- fab/vidi: ^5 || ^6 || dev-master
- typo3/cms-backend: ^11.0
- typo3/cms-core: ^11.0
- typo3/cms-extbase: ^11.0
- typo3/cms-frontend: ^11.0
Replaces
- fab/vidi_frontend: 5.0.10
This package is auto-updated.
Last update: 2024-08-23 13:33:10 UTC
README
通用列表组件,可以以高级方式过滤内容... 来了,看到了,征服了!本扩展基于 Vidi,在后端提供类似的功能集。
安装后,可以在后端插件记录中配置要渲染的内容类型,并关联自定义模板。在前端,我们使用优秀的 DataTables,这是一个智能且快速排序和过滤数据的jQuery插件。过滤器条由 Visual Search jQuery插件提供,它提供了很好的分面能力和直观的搜索。
实时示例 http://www.washinhcf.org/resources/publications/
兼容性和维护
此包目前正在以下版本上维护
项目信息和版本
稳定版本: https://extensions.typo3.org/extension/vidi_frontend/
开发版本: https://github.com/fabarea/vidi_frontend
git clone https://github.com/fabarea/vidi_frontend.git
有关最新开发的新闻也发布在 http://twitter.com/fudriot
安装和需求
首选方式是使用Composer安装扩展,如下所示
composer require fab/vidi-frontend
# -> next step is to open the BE and activate the extension in the Extension Manager.
你几乎完成了!在 General Plugin
> Generic List Component
中创建一个类型为 "Vidi Frontend" 的内容元素,并按需配置。
基于模板的显示
从Vidi Frontend 1.3开始,可以配置自定义模板来显示记录。我们可以通过TypoScript注册新模板。
plugin.tx_vidifrontend {
settings {
# Used in plugin "Generic List - with template
listTemplates {
# We disable existing template for demo purposes
1 >
# Best is to use a key as of 100 to not override existing configuration
# Tip: get inspired by EXT:vidi_frontend/Resources/Private/Standalone/DemoTemplateList.html
100 {
label = My specila list
path = EXT:my_extension/Resources/Private/Standalone/MyList.html
additionalSettingsHelp (
# We can add additional settings tip for the BE user.
# The settings will be passed to list view.
)
}
}
}
}
开始编辑模板文件 EXT:my_extension/Resources/Private/Standalone/MyList.html
。
路由增强器
对于TYPO3 v9,需要添加到 /config/sites/[SITE_IDENTIFIER]/config.yml
。
routeEnhancers: VidiFrontend: type: Plugin # limitToPages: [12] routePath: '/content/{action}/{contentElement}-{content}' namespace: 'tx_vidifrontend_pi1' defaults: action: "show" requirements: content: '[0-9].*' contentElement: '[0-9].*'
配置
该插件可以在多个地方进行配置,如TypoScript、PHP或插件记录本身。
重要 默认情况下,为Bootstrap加载了CSS + JS文件。对于更Vanilla的口味,编辑TypoScript中的settings
键中的path
,并加载您自己的正确资产。以下是一些注释:
#############################
# plugin.tx_vidifrontend
#############################
plugin.tx_vidifrontend {
settings {
asset {
vidiCss {
# For none Bootstrap replace "vidi_frontend.bootstrap.min.css" by "vidi_frontend.min.css"
path = EXT:vidi_frontend/Resources/Public/Build/StyleSheets/vidi_frontend.bootstrap.min.css
type = css
}
vidiJs {
# For none Bootstrap replace "vidi_frontend.bootstrap.min.js" by "vidi_frontend.min.js"
path = EXT:vidi_frontend/Resources/Public/Build/JavaScript/vidi_frontend.bootstrap.min.js
type = js
}
}
}
}
自定义网格渲染器
假设我们想要对列进行完全自定义的输出,我们可以通过实现网格渲染来实现。以下是一个针对表fe_users
的示例。我们首先必须在某个Configuration/TCA/Override/fe_users.php
中注册新列。
$tca = [ 'grid_frontend' => [ 'columns' => [ # The key is totally free here. However we prefix with "__" to distinguish between a "regular" column associated to a field. '__my_custom_column' => [ 'renderers' => array( 'Vendor\MyExt\Grid\MyColumnRenderer', ), 'sorting' => FALSE, 'sortable' => FALSE, 'label' => '', ], ], ], ]; \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($GLOBALS['TCA']['fe_users'], $tca);
要放置在EXT:MyExt/Classes/Grid/MyColumnRenderer
中的相应类
namespace Vendor\MyExt\Grid; /** * Class to render a custom output. */ class MyColumnRenderer extends Fab\Vidi\Grid\ColumnRendererAbstract { /** * Render a publication. * * @return string */ public function render() { return $output; }
调整列配置
列配置来自TCA。有时我们需要调整其配置以适应前端,我们可以简单地丰富它。最好的方法是学习示例并从EXT:vidi_frontend/Configuration/TCA/fe_users.php
中获取灵感
$tca = array( 'grid_frontend' => array( 'columns' => array( # Custom fields for the FE goes here 'title' => [], ), ), );
自定义分面
在视觉搜索中可见的方面可以通过标准进行搜索。方面通常映射到一个字段,但不是强制的;它可以是任意值。要提供自定义方面,必须实现接口\Fab\Vidi\Facet\FacetInterface
。最佳做法是借鉴\Fab\Vidi\Facet\StandardFacet
并提供自己的实现。
$tca = [ 'grid_frontend' => [ 'facets' => [ new \Vendor\MyExt\Facets\MyCustomFacet(), ], ], ]; \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($GLOBALS['TCA']['fe_users'], $tca);
关联类
<?php namespace Vendor\MyExt\Facets; use Fab\Vidi\Facet\FacetInterface; use Fab\Vidi\Facet\StandardFacet; use Fab\Vidi\Persistence\Matcher; /** * Class for configuring a custom Facet item. */ class CategoryPublicationFacet implements FacetInterface { /** * @var string */ protected $name = '__categories_publications'; /** * @var string */ protected $label = 'Categories'; /** * @var array */ protected $suggestions = []; /** * @var string */ protected $fieldNameAndPath = 'metadata.categories'; /** * @var string */ protected $dataType; /** * @var string */ protected $canModifyMatcher = true; /** * Constructor of a Generic Facet in Vidi. * * @param string $name * @param string $label * @param array $suggestions * @param string $fieldNameAndPath */ public function __construct($name = '', $label = '', array $suggestions = [], $fieldNameAndPath = '') { } /** * @return string */ public function getName() { return $this->name; } /** * @return string */ public function getLabel() { return $this->label; } /** * @return array */ public function getSuggestions() { return [1 => 'foo', 2 => 'bar', ]; } /** * @return bool */ public function hasSuggestions() { return true; } /** * @return string */ public function getFieldNameAndPath() { return $this->fieldNameAndPath; } /** * @param string $dataType * @return $this */ public function setDataType($dataType) { $this->dataType = $dataType; return $this; } /** * @return bool */ public function canModifyMatcher() { return $this->canModifyMatcher; } /** * @param Matcher $matcher * @param $value * @return Matcher */ public function modifyMatcher(Matcher $matcher, $value) { if (MathUtility::canBeInterpretedAsInteger($value)) { $matcher->equals('metadata.categories', $value); } else { $matcher->like('metadata.categories', $value); } return $matcher; } /** * Magic method implementation for retrieving state. * * @param array $states * @return StandardFacet */ static public function __set_state($states) { return new CategoryPublicationFacet($states['name'], $states['label'], $states['suggestions'], $states['fieldNameAndPath']); } }
注册新模板
内容的详细视图可以根据插件记录进行个性化。要注册更多模板,只需在您的TypoScript配置中定义它们。此TypoScript通常位于EXT:foo/Configuration/TypoScript/setup.txt
下。
plugin.tx_vidifrontend {
settings {
templates {
# Key "1", "2" is already taken by this extension.
# Use key "10", "11" and following for your own templates to be safe.
10 {
title = Foo detail view
path = EXT:foo/Resources/Private/Templates/VidiFrontend/ShowFoo.html
dataType = fe_users
}
}
}
}
添加自定义约束
如果需要在“低”级别添加额外的自定义约束,可以利用Vidi内容库中的信号槽。要这样做,首先在您的ext_localconf.php
文件中注册槽。
$signalSlotDispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\SignalSlot\Dispatcher'); $signalSlotDispatcher->connect( 'Fab\Vidi\Domain\Repository\ContentRepository', 'postProcessConstraintsObject', 'Vendor\Extension\Aspects\ProductsAspect', 'processConstraints', true );
下一步是编写和定制如以下示例所示的PHP类。您可以自由地操作$constraints对象,并根据自己的需要进行个性化。
<?php namespace Vendor\Extension\Aspects; use Fab\Vidi\Persistence\Query; use TYPO3\CMS\Extbase\Persistence\Generic\Qom\ConstraintInterface; /** * Class which handle signal slot for Vidi Content controller */ class ProductsAspect { /** * Post-process the constraints object to respect the file mounts. * * @param Query $query * @param ConstraintInterface|null $constraints * @param $constraintContainer|null * @return array */ public function processConstraints(Query $query, $constraints, $constraintContainer) { if ($this->isFrontendMode() && $query->getType() === 'tt_products') { $additionalConstraints = $query->logicalAnd( $query->logicalNot($query->equals('title', '')), $query->logicalNot($query->equals('image', '')) ); $constraints = null === $constraints ? $additionalConstraints : $query->logicalAnd( $constraints, $additionalConstraints ); } return [$query, $constraints, $constraintContainer]; } /** * Returns whether the current mode is Frontend * * @return bool */ protected function isFrontendMode() { return TYPO3_MODE === 'FE'; } }
传递动态参数
我们可以传递额外的GET/POST参数,以在网格中动态过滤结果集。一个典型的用例是添加下拉菜单以进行额外的筛选。在这种情况下,参数名称必须看起来像“foo”是字段名。值可以是简单值(等于)或CSV列表,它将被解释为数组(在)。
tx_vididfrontend_pi1[matches][foo]=bar
tx_vididfrontend_pi1[matches][foo]=bar,baz
添加自定义动作
默认情况下,Vidi前端包括一些默认的大规模动作,例如XML、CSV、XLS导出。当然,可以添加自己的动作。这需要两个步骤。第一步是在TCA中声明。
$tca = array( 'grid_frontend' => [ 'columns' => [ ... ], 'actions' => [ \Vendor\MyExt\MassAction\MyAction::class, ] ], ); \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($GLOBALS['TCA']['tx_domain_model_foo'], $tca);
然后,您需要声明自己的类并实现MassActionInterface
,其中有两个主要方法
render()
,其中组装菜单项的HTML。execute()
,其中我们从请求中获取项并根据我们的需求处理它们。execute()
方法必须返回一个包含响应以及可能的发送到客户端(浏览器)的头的ResultActionInterface
。
<?php namespace Vendor\MyExt\MassAction; use Fab\VidiFrontend\Service\ContentService; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; /** * Class MyAction */ class MyAction extends AbstractMassAction { /** * @var string */ protected $name = 'my_action'; /** * @return string */ public function render() { $result = sprintf('<li><a href="%s" class="export-csv" data-format="csv"><i class="fa fa-file-text-o"></i> %s</a></li>', $this->getMassActionUrl(), LocalizationUtility::translate('my_action', 'foo') ); return $result; } /** * Return the name of this action.. * * @return string */ public function getName() { return $this->name; } /** * Execute the action. * * @param ContentService $contentService * @return ResultActionInterface */ public function execute(ContentService $contentService) { $result = new JsonResultAction(); $objects = $contentService->getObjects(); // Make sure we have something to process... if ((bool)$objects) { // do something ... $result->setOuptut('foo') } return $result; } }
在此基础上,您可能还需要加载自己的JS来捕获动作并在客户端触发必要的动作,例如Ajax请求。
RealURL配置
RealURL配置可以如下所示,以显示漂亮的URL到详细视图。
'postVarSets' => [ '_DEFAULT' => [ 'content' => [ ['GETvar' => 'tx_vidifrontend_pi1[contentElement]'], ['GETvar' => 'tx_vidifrontend_pi1[action]'], ['GETvar' => 'tx_vidifrontend_pi1[content]'], ], ] ],
在开发中构建资产
该扩展提供了包含所有必要代码的JS/CSS包。如果您需要为这些JS/CSS文件创建新的构建,请考虑Bower和Grunt必须作为先决条件安装到您的系统上。
安装所需的Web组件
cd typo3conf/ext/vidi_frontend # This will populate the directory Resources/Private/BowerComponents. bower install # Install the necessary NodeJS package. npm install
然后,您可以运行扩展的Grunt来生成构建
cd typo3conf/ext/vidi_frontend
grunt build
在开发过程中,您可以使用watch
,这样在您编辑文件时就会生成构建
grunt watch
修复VisualSearch
为了改善用户体验,Visual Search插件已被修复,避免下拉菜单意外出现。这意味着在创建新构建时,补丁(目前)必须手动添加。
cd Resources/Private/BowerComponents/visualsearch/ grep -lr "app.searchBox.searchEvent(e)" . -> There should be 2 occurrences. Comment lines below related to "_.defer". # Remove assumed already jQuery from dependency curl http://documentcloud.github.io/visualsearch/vendor/jquery.ui.core.js > Resources/Private/BowerComponents/visualsearch/build-min/dependencies.js curl http://documentcloud.github.io/visualsearch/vendor/jquery.ui.position.js >> Resources/Private/BowerComponents/visualsearch/build-min/dependencies.js curl http://documentcloud.github.io/visualsearch/vendor/jquery.ui.widget.js >> Resources/Private/BowerComponents/visualsearch/build-min/dependencies.js curl http://documentcloud.github.io/visualsearch/vendor/jquery.ui.menu.js >> Resources/Private/BowerComponents/visualsearch/build-min/dependencies.js curl http://documentcloud.github.io/visualsearch/vendor/jquery.ui.autocomplete.js >> Resources/Private/BowerComponents/visualsearch/build-min/dependencies.js curl http://documentcloud.github.io/visualsearch/vendor/underscore-1.5.2.js >> Resources/Private/BowerComponents/visualsearch/build-min/dependencies.js curl http://documentcloud.github.io/visualsearch/vendor/backbone-1.1.0.js >> Resources/Private/BowerComponents/visualsearch/build-min/dependencies.js