mirror of
https://github.com/werkraum-media/thuecat.git
synced 2024-12-04 19:16:13 +01:00
Add new page type for tourist attraction
Allows to select a single tourist attraction. Provides static TypoScript to resolve reference for Fluid based rendering.
This commit is contained in:
parent
16ae83e841
commit
775db67efa
21 changed files with 237 additions and 21 deletions
|
@ -24,7 +24,10 @@ namespace WerkraumMedia\ThueCat;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use TYPO3\CMS\Core\Cache\Backend\TransientMemoryBackend;
|
use TYPO3\CMS\Core\Cache\Backend\TransientMemoryBackend;
|
||||||
|
use TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider;
|
||||||
|
use TYPO3\CMS\Core\Imaging\IconRegistry;
|
||||||
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
|
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
|
||||||
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
use TYPO3\CMS\Extbase\Utility\ExtensionUtility;
|
use TYPO3\CMS\Extbase\Utility\ExtensionUtility;
|
||||||
use WerkraumMedia\ThueCat\Controller\Backend\ImportController;
|
use WerkraumMedia\ThueCat\Controller\Backend\ImportController;
|
||||||
use WerkraumMedia\ThueCat\Controller\Backend\OverviewController;
|
use WerkraumMedia\ThueCat\Controller\Backend\OverviewController;
|
||||||
|
@ -35,7 +38,9 @@ class Extension
|
||||||
|
|
||||||
public const EXTENSION_NAME = 'Thuecat';
|
public const EXTENSION_NAME = 'Thuecat';
|
||||||
|
|
||||||
public const TT_CONTENT_GROUP = 'thuecat';
|
public const TCA_SELECT_GROUP_IDENTIFIER = 'thuecat';
|
||||||
|
|
||||||
|
public const PAGE_DOKTYPE_TOURIST_ATTRACTION = 950;
|
||||||
|
|
||||||
public static function getLanguagePath(): string
|
public static function getLanguagePath(): string
|
||||||
{
|
{
|
||||||
|
@ -65,6 +70,8 @@ class Extension
|
||||||
{
|
{
|
||||||
self::addCaching();
|
self::addCaching();
|
||||||
self::addContentElements();
|
self::addContentElements();
|
||||||
|
self::addPageTypes();
|
||||||
|
self::addIcons();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getIconPath(): string
|
public static function getIconPath(): string
|
||||||
|
@ -76,7 +83,6 @@ class Extension
|
||||||
{
|
{
|
||||||
$languagePath = self::getLanguagePath() . 'locallang_tca.xlf:tt_content';
|
$languagePath = self::getLanguagePath() . 'locallang_tca.xlf:tt_content';
|
||||||
|
|
||||||
// TODO: Add Icon
|
|
||||||
ExtensionManagementUtility::addPageTSConfig('
|
ExtensionManagementUtility::addPageTSConfig('
|
||||||
mod.wizards.newContentElement.wizardItems.thuecat {
|
mod.wizards.newContentElement.wizardItems.thuecat {
|
||||||
header = ' . $languagePath . '.group
|
header = ' . $languagePath . '.group
|
||||||
|
@ -85,6 +91,7 @@ class Extension
|
||||||
thuecat_tourist_attraction{
|
thuecat_tourist_attraction{
|
||||||
title = ' . $languagePath . '.thuecat_tourist_attraction
|
title = ' . $languagePath . '.thuecat_tourist_attraction
|
||||||
description = ' . $languagePath . '.thuecat_tourist_attraction.description
|
description = ' . $languagePath . '.thuecat_tourist_attraction.description
|
||||||
|
iconIdentifier = tx_thuecat_tourist_attraction
|
||||||
tt_content_defValues {
|
tt_content_defValues {
|
||||||
CType = thuecat_tourist_attraction
|
CType = thuecat_tourist_attraction
|
||||||
}
|
}
|
||||||
|
@ -94,6 +101,30 @@ class Extension
|
||||||
');
|
');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function addPageTypes(): void
|
||||||
|
{
|
||||||
|
ExtensionManagementUtility::addUserTSConfig(
|
||||||
|
"@import 'EXT:" . self::EXTENSION_KEY . "/Configuration/TSconfig/User/All.tsconfig'"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function addIcons(): void
|
||||||
|
{
|
||||||
|
$iconFiles = GeneralUtility::getFilesInDir(GeneralUtility::getFileAbsFileName(self::getIconPath()));
|
||||||
|
if (is_array($iconFiles) === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$iconRegistry = GeneralUtility::makeInstance(IconRegistry::class);
|
||||||
|
foreach ($iconFiles as $iconFile) {
|
||||||
|
$iconRegistry->registerIcon(
|
||||||
|
str_replace('.svg', '', $iconFile),
|
||||||
|
SvgIconProvider::class,
|
||||||
|
['source' => self::getIconPath() . $iconFile]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static function addCaching(): void
|
private static function addCaching(): void
|
||||||
{
|
{
|
||||||
$cacheIdentifier = 'thuecat_fetchdata';
|
$cacheIdentifier = 'thuecat_fetchdata';
|
||||||
|
|
|
@ -52,6 +52,10 @@ class ResolveEntities implements DataProcessorInterface
|
||||||
array $processorConfiguration,
|
array $processorConfiguration,
|
||||||
array $processedData
|
array $processedData
|
||||||
) {
|
) {
|
||||||
|
if (isset($processorConfiguration['if.']) && !$cObj->checkIf($processorConfiguration['if.'])) {
|
||||||
|
return $processedData;
|
||||||
|
}
|
||||||
|
|
||||||
$as = $cObj->stdWrapValue('as', $processorConfiguration, 'entities');
|
$as = $cObj->stdWrapValue('as', $processorConfiguration, 'entities');
|
||||||
$tableName = $cObj->stdWrapValue('table', $processorConfiguration, '');
|
$tableName = $cObj->stdWrapValue('table', $processorConfiguration, '');
|
||||||
$uids = $cObj->stdWrapValue('uids', $processorConfiguration, '');
|
$uids = $cObj->stdWrapValue('uids', $processorConfiguration, '');
|
||||||
|
|
30
Configuration/FlexForm/Pages/tourist_attraction.xml
Normal file
30
Configuration/FlexForm/Pages/tourist_attraction.xml
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<T3DataStructure>
|
||||||
|
<meta>
|
||||||
|
<langDisable>1</langDisable>
|
||||||
|
</meta>
|
||||||
|
<sheets>
|
||||||
|
<sDEF>
|
||||||
|
<ROOT>
|
||||||
|
<TCEforms>
|
||||||
|
<sheetTitle>LLL:EXT:thuecat/Resources/Private/Language/locallang_flexform.xlf:pages.tourist_attraction.sheetTitle</sheetTitle>
|
||||||
|
</TCEforms>
|
||||||
|
<type>array</type>
|
||||||
|
<el>
|
||||||
|
<touristAttraction>
|
||||||
|
<TCEforms>
|
||||||
|
<label>LLL:EXT:thuecat/Resources/Private/Language/locallang_flexform.xlf:pages.tourist_attraction.tourist_attraction</label>
|
||||||
|
<config>
|
||||||
|
<type>select</type>
|
||||||
|
<renderType>selectMultipleSideBySide</renderType>
|
||||||
|
<foreign_table>tx_thuecat_tourist_attraction</foreign_table>
|
||||||
|
<foreign_table_where>AND {#tx_thuecat_tourist_attraction}.{#sys_language_uid} IN (0,-1)</foreign_table_where>
|
||||||
|
<minitems>1</minitems>
|
||||||
|
<maxitems>1</maxitems>
|
||||||
|
</config>
|
||||||
|
</TCEforms>
|
||||||
|
</touristAttraction>
|
||||||
|
</el>
|
||||||
|
</ROOT>
|
||||||
|
</sDEF>
|
||||||
|
</sheets>
|
||||||
|
</T3DataStructure>
|
39
Configuration/TCA/Overrides/pages.php
Normal file
39
Configuration/TCA/Overrides/pages.php
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
defined('TYPO3') or die();
|
||||||
|
|
||||||
|
(static function (string $extensionKey, string $tableName) {
|
||||||
|
$languagePath = \WerkraumMedia\ThueCat\Extension::getLanguagePath()
|
||||||
|
. 'locallang_tca.xlf:' . $tableName;
|
||||||
|
|
||||||
|
\TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($GLOBALS['TCA'][$tableName], [
|
||||||
|
'columns' => [
|
||||||
|
'tx_thuecat_flexform' => [
|
||||||
|
'label' => $languagePath . '.tx_thuecat_flexform',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'flex',
|
||||||
|
'ds_pointerField' => 'doktype',
|
||||||
|
'ds' => [
|
||||||
|
'default' => '<T3DataStructure> <ROOT> <type>array</type> <el> <!-- Repeat an element like "xmlTitle" beneath for as many elements you like. Remember to name them uniquely --> <xmlTitle> <TCEforms> <label>The Title:</label> <config> <type>input</type> <size>48</size> </config> </TCEforms> </xmlTitle> </el> </ROOT> </T3DataStructure>',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'palettes' => [
|
||||||
|
'tx_thuecat' => [
|
||||||
|
'label' => $languagePath . 'palette.tx_thuecat',
|
||||||
|
'showitem' => 'tx_thuecat_flexform',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItemGroup(
|
||||||
|
$tableName,
|
||||||
|
'doktype',
|
||||||
|
\WerkraumMedia\ThueCat\Extension::TCA_SELECT_GROUP_IDENTIFIER,
|
||||||
|
$languagePath . '.group'
|
||||||
|
);
|
||||||
|
})(
|
||||||
|
\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY,
|
||||||
|
'pages'
|
||||||
|
);
|
72
Configuration/TCA/Overrides/pages_tourist_attraction.php
Normal file
72
Configuration/TCA/Overrides/pages_tourist_attraction.php
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
defined('TYPO3') or die();
|
||||||
|
|
||||||
|
(static function (string $extensionKey, string $tableName, int $doktype, string $pageIdentifier) {
|
||||||
|
$languagePath = \WerkraumMedia\ThueCat\Extension::getLanguagePath()
|
||||||
|
. 'locallang_tca.xlf:' . $tableName . '.' . $pageIdentifier;
|
||||||
|
|
||||||
|
\TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($GLOBALS['TCA'][$tableName], [
|
||||||
|
'ctrl' => [
|
||||||
|
'typeicon_classes' => [
|
||||||
|
$doktype => $tableName . '_' . $pageIdentifier,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'types' => [
|
||||||
|
$doktype => [
|
||||||
|
'showitem' => ''
|
||||||
|
. '--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general,'
|
||||||
|
. 'doktype,'
|
||||||
|
. '--palette--;;title,'
|
||||||
|
. '--palette--;;tx_thuecat,'
|
||||||
|
. '--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.metadata,'
|
||||||
|
. '--palette--;;abstract,'
|
||||||
|
. '--palette--;;editorial,'
|
||||||
|
. '--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.appearance,'
|
||||||
|
. '--palette--;;layout,'
|
||||||
|
. '--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.behaviour,'
|
||||||
|
. '--palette--;;links,'
|
||||||
|
. '--palette--;;miscellaneous,'
|
||||||
|
. '--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.resources,'
|
||||||
|
. '--palette--;;media,'
|
||||||
|
. '--palette--;;config,'
|
||||||
|
. '--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language,'
|
||||||
|
. '--palette--;;language,'
|
||||||
|
. '--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.access,'
|
||||||
|
. '--palette--;;visibility,'
|
||||||
|
. '--palette--;;access,'
|
||||||
|
. '--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:categories,'
|
||||||
|
. '--div--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_category.tabs.category,'
|
||||||
|
. 'categories,'
|
||||||
|
. '--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:notes,'
|
||||||
|
. 'rowDescription,'
|
||||||
|
. '--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:extended',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'columns' => [
|
||||||
|
'tx_thuecat_flexform' => [
|
||||||
|
'config' => [
|
||||||
|
'ds' => [
|
||||||
|
$doktype => 'FILE:EXT:' . $extensionKey . '/Configuration/FlexForm/Pages/' . $pageIdentifier . '.xml',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItem(
|
||||||
|
$tableName,
|
||||||
|
'doktype',
|
||||||
|
[
|
||||||
|
$languagePath,
|
||||||
|
$doktype,
|
||||||
|
\WerkraumMedia\ThueCat\Extension::getIconPath() . $tableName . '_' . $pageIdentifier . '.svg',
|
||||||
|
\WerkraumMedia\ThueCat\Extension::TCA_SELECT_GROUP_IDENTIFIER,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
})(
|
||||||
|
\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY,
|
||||||
|
'pages',
|
||||||
|
\WerkraumMedia\ThueCat\Extension::PAGE_DOKTYPE_TOURIST_ATTRACTION,
|
||||||
|
'tourist_attraction'
|
||||||
|
);
|
|
@ -5,8 +5,13 @@ defined('TYPO3') or die();
|
||||||
(static function (string $extensionKey, string $tableName) {
|
(static function (string $extensionKey, string $tableName) {
|
||||||
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile(
|
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile(
|
||||||
$extensionKey,
|
$extensionKey,
|
||||||
'Configuration/TypoScript/',
|
'Configuration/TypoScript/ContentElements',
|
||||||
'ThüCAT'
|
'ThüCAT - Content Elements'
|
||||||
|
);
|
||||||
|
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile(
|
||||||
|
$extensionKey,
|
||||||
|
'Configuration/TypoScript/PageTypes',
|
||||||
|
'ThüCAT - Page Types'
|
||||||
);
|
);
|
||||||
})(
|
})(
|
||||||
\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY,
|
\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY,
|
||||||
|
|
|
@ -9,7 +9,7 @@ defined('TYPO3') or die();
|
||||||
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItemGroup(
|
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItemGroup(
|
||||||
$tableName,
|
$tableName,
|
||||||
'CType',
|
'CType',
|
||||||
\WerkraumMedia\ThueCat\Extension::TT_CONTENT_GROUP,
|
\WerkraumMedia\ThueCat\Extension::TCA_SELECT_GROUP_IDENTIFIER,
|
||||||
$languagePath . '.group'
|
$languagePath . '.group'
|
||||||
);
|
);
|
||||||
})(
|
})(
|
||||||
|
|
|
@ -8,10 +8,9 @@ defined('TYPO3') or die();
|
||||||
|
|
||||||
\TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($GLOBALS['TCA'][$tableName], [
|
\TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($GLOBALS['TCA'][$tableName], [
|
||||||
'ctrl' => [
|
'ctrl' => [
|
||||||
// TODO: Add Icon
|
'typeicon_classes' => [
|
||||||
// 'typeicon_classes' => [
|
$cType => 'tx_' . $cType,
|
||||||
// $cType => '',
|
],
|
||||||
// ],
|
|
||||||
],
|
],
|
||||||
'types' => [
|
'types' => [
|
||||||
$cType => [
|
$cType => [
|
||||||
|
@ -56,9 +55,8 @@ defined('TYPO3') or die();
|
||||||
[
|
[
|
||||||
$languagePath,
|
$languagePath,
|
||||||
$cType,
|
$cType,
|
||||||
// TODO: Add Icon
|
\WerkraumMedia\ThueCat\Extension::getIconPath() . 'tx_' . $cType . '.svg',
|
||||||
'',
|
\WerkraumMedia\ThueCat\Extension::TCA_SELECT_GROUP_IDENTIFIER,
|
||||||
\WerkraumMedia\ThueCat\Extension::TT_CONTENT_GROUP,
|
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
})(
|
})(
|
||||||
|
|
1
Configuration/TSconfig/User/All.tsconfig
Normal file
1
Configuration/TSconfig/User/All.tsconfig
Normal file
|
@ -0,0 +1 @@
|
||||||
|
@import 'EXT:thuecat/Configuration/TSconfig/User/PageTypes/*.tsconfig'
|
|
@ -0,0 +1 @@
|
||||||
|
options.pageTree.doktypesToShowInNewPageDragArea := addToList(950)
|
|
@ -0,0 +1 @@
|
||||||
|
@import 'EXT:thuecat/Configuration/TypoScript/ContentElements/Rendering/*.typoscript'
|
|
@ -0,0 +1,16 @@
|
||||||
|
page {
|
||||||
|
10 {
|
||||||
|
dataProcessing {
|
||||||
|
950 = WerkraumMedia\ThueCat\Frontend\DataProcessing\ResolveEntities
|
||||||
|
950 {
|
||||||
|
as = touristAttraction
|
||||||
|
if {
|
||||||
|
isInList.data = page:doktype
|
||||||
|
value = 950
|
||||||
|
}
|
||||||
|
table = tx_thuecat_tourist_attraction
|
||||||
|
uids.data = flexform:tx_thuecat_flexform:touristAttraction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
Configuration/TypoScript/PageTypes/setup.typoscript
Normal file
1
Configuration/TypoScript/PageTypes/setup.typoscript
Normal file
|
@ -0,0 +1 @@
|
||||||
|
@import 'EXT:thuecat/Configuration/TypoScript/PageTypes/Rendering/*.typoscript'
|
|
@ -1,6 +0,0 @@
|
||||||
lib.thuecatContentElement =< lib.contentElement
|
|
||||||
lib.thuecatContentElement {
|
|
||||||
templateRootPaths {
|
|
||||||
9999 = EXT:thuecat/Resources/Private/Templates/Frontend/ContentElement/
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
@import 'EXT:thuecat/Configuration/TypoScript/Rendering/*.typoscript'
|
|
|
@ -40,9 +40,9 @@ The extension already allows:
|
||||||
|
|
||||||
* Content element to display tourist attraction
|
* Content element to display tourist attraction
|
||||||
|
|
||||||
## Short time goals
|
* Page Type to reference tourist attraction
|
||||||
|
|
||||||
* Integrate proper icons
|
## Short time goals
|
||||||
|
|
||||||
* Content element to display town, tourist information and organisation.
|
* Content element to display town, tourist information and organisation.
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,13 @@
|
||||||
<trans-unit id="importConfiguration.static.url" xml:space="preserve">
|
<trans-unit id="importConfiguration.static.url" xml:space="preserve">
|
||||||
<source>URL</source>
|
<source>URL</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
|
||||||
|
<trans-unit id="pages.tourist_attraction.sheetTitle" xml:space="preserve">
|
||||||
|
<source>Tourist Attraction</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="pages.tourist_attraction.tourist_attraction" xml:space="preserve">
|
||||||
|
<source>Tourist Attraction</source>
|
||||||
|
</trans-unit>
|
||||||
</body>
|
</body>
|
||||||
</file>
|
</file>
|
||||||
</xliff>
|
</xliff>
|
||||||
|
|
|
@ -181,6 +181,19 @@
|
||||||
<trans-unit id="tt_content.thuecat_tourist_attraction.description" xml:space="preserve">
|
<trans-unit id="tt_content.thuecat_tourist_attraction.description" xml:space="preserve">
|
||||||
<source>Renders selected tourist attractions</source>
|
<source>Renders selected tourist attractions</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
|
||||||
|
<trans-unit id="pages.group" xml:space="preserve">
|
||||||
|
<source>ThüCAT</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="pages.tourist_attraction" xml:space="preserve">
|
||||||
|
<source>Tourist Attraction</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="pages.palette.tx_thuecat" xml:space="preserve">
|
||||||
|
<source>ThüCAT</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="pages.tx_thuecat_flexform" xml:space="preserve">
|
||||||
|
<source>Configuration</source>
|
||||||
|
</trans-unit>
|
||||||
</body>
|
</body>
|
||||||
</file>
|
</file>
|
||||||
</xliff>
|
</xliff>
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
CREATE TABLE pages (
|
||||||
|
tx_thuecat_flexform text,
|
||||||
|
);
|
||||||
|
|
||||||
CREATE TABLE tx_thuecat_import_configuration (
|
CREATE TABLE tx_thuecat_import_configuration (
|
||||||
title varchar(255) DEFAULT '' NOT NULL,
|
title varchar(255) DEFAULT '' NOT NULL,
|
||||||
type varchar(255) DEFAULT '' NOT NULL,
|
type varchar(255) DEFAULT '' NOT NULL,
|
||||||
|
|
Loading…
Reference in a new issue