Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0b23b37b9 | ||
|
|
88fac7313e | ||
|
|
de3bbbe2f5 | ||
|
|
b794257f61 | ||
|
|
f4e024a9f8 | ||
|
|
73fe876c78 | ||
|
|
c7f6a6ec44 | ||
|
|
8302214657 | ||
|
|
1d7fadbd19 | ||
|
|
c0c81317aa | ||
|
|
32c0c89785 | ||
|
|
4ca38821fb | ||
|
|
b39f17886f |
No files matched your search
@@ -6,5 +6,10 @@ nbproject
|
||||
/vendor
|
||||
/public/*
|
||||
!/public/.htaccess
|
||||
# Third-party files that have to be served from the site root
|
||||
!/public/chat.bundle.es.js
|
||||
!/public/chat.styles.css
|
||||
!/public/cleverpush-manifest.json
|
||||
!/public/cleverpush-worker.js
|
||||
/node_modules
|
||||
/packages/ep_theme/Resources/Public/
|
||||
@@ -49,7 +49,8 @@
|
||||
"typo3/cms-sys-note": "^13.4",
|
||||
"typo3/cms-tstemplate": "^13.4",
|
||||
"typo3/cms-viewpage": "^13.4",
|
||||
"typo3/cms-webhooks": "^13.4"
|
||||
"typo3/cms-webhooks": "^13.4",
|
||||
"yoast-seo-for-typo3/yoast_seo": "^12.1"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "f1134476988f3bf5d2a3a74092cdb285",
|
||||
"content-hash": "c1db37c5c31e87b85ee7db5788ca99c8",
|
||||
"packages": [
|
||||
{
|
||||
"name": "b13/container",
|
||||
@@ -2055,6 +2055,79 @@
|
||||
},
|
||||
"time": "2026-08-18T06:18:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "maxserv/frontend-request",
|
||||
"version": "2.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MaxServ/frontend-request.git",
|
||||
"reference": "527296df01a6370bf3ad40d6514a3538129f1bc6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/MaxServ/frontend-request/zipball/527296df01a6370bf3ad40d6514a3538129f1bc6",
|
||||
"reference": "527296df01a6370bf3ad40d6514a3538129f1bc6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"php": "^8.2",
|
||||
"typo3/cms-backend": "^12.4.25 || ^13.4 || ^14.1",
|
||||
"typo3/cms-core": "^12.4.25 || ^13.4 || ^14.1",
|
||||
"typo3/cms-frontend": "^12.4.25 || ^13.4 || ^14.1"
|
||||
},
|
||||
"replace": {
|
||||
"typo3-ter/frontend-request": "self.version"
|
||||
},
|
||||
"require-dev": {
|
||||
"composer/class-map-generator": "^1.3.4",
|
||||
"dg/bypass-finals": "^1.8",
|
||||
"ergebnis/composer-normalize": "^2.43",
|
||||
"friendsofphp/php-cs-fixer": "^3.60.0",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.4",
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "^1.12 || ^2.1",
|
||||
"phpunit/phpunit": "^10.1 || ^11.2.5",
|
||||
"saschaegerer/phpstan-typo3": "^1.10 || ^2.1 || ^3.0.1",
|
||||
"typo3/coding-standards": "^0.7.1 || ^0.8.0",
|
||||
"typo3/testing-framework": "^7.1.0 || ^8.2.0 || ^9.5.0"
|
||||
},
|
||||
"type": "typo3-cms-extension",
|
||||
"extra": {
|
||||
"typo3/cms": {
|
||||
"web-dir": ".Build/public",
|
||||
"extension-key": "frontend_request"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"MaxServ\\FrontendRequest\\": "Classes/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"GPL-3.0-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Team MaxServ",
|
||||
"email": "[email protected]",
|
||||
"homepage": "https://maxserv.com"
|
||||
}
|
||||
],
|
||||
"description": "Helper extension to make a frontend request from the backend of TYPO3 using javascript.",
|
||||
"homepage": "https://maxserv.com",
|
||||
"keywords": [
|
||||
"MaxServ",
|
||||
"TYPO3 CMS"
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://docs.typo3.org/p/maxserv/frontend_request/main/en-us/",
|
||||
"issues": "https://github.com/MaxServ/frontend-request/issues",
|
||||
"source": "https://github.com/MaxServ/frontend-request"
|
||||
},
|
||||
"time": "2026-04-30T08:31:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
"version": "v5.9.0",
|
||||
@@ -8855,6 +8928,95 @@
|
||||
"source": "https://github.com/webmozarts/assert/tree/2.5.0"
|
||||
},
|
||||
"time": "2026-10-05T23:14:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "yoast-seo-for-typo3/yoast_seo",
|
||||
"version": "12.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Yoast/Yoast-SEO-for-TYPO3.git",
|
||||
"reference": "1287de1607a20976390a5adaaa6db57f2301a4c5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Yoast/Yoast-SEO-for-TYPO3/zipball/1287de1607a20976390a5adaaa6db57f2301a4c5",
|
||||
"reference": "1287de1607a20976390a5adaaa6db57f2301a4c5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"maxserv/frontend-request": "^2.0",
|
||||
"php": "^8.2",
|
||||
"typo3/cms-backend": "^12.4.25 || ^13.4 || ^14.3",
|
||||
"typo3/cms-core": "^12.4.25 || ^13.4 || ^14.3",
|
||||
"typo3/cms-extbase": "^12.4.25 || ^13.4 || ^14.3",
|
||||
"typo3/cms-fluid": "^12.4.25 || ^13.4 || ^14.3",
|
||||
"typo3/cms-frontend": "^12.4.25 || ^13.4 || ^14.3",
|
||||
"typo3/cms-install": "^12.4.25 || ^13.4 || ^14.3",
|
||||
"typo3/cms-seo": "^12.4.25 || ^13.4 || ^14.3"
|
||||
},
|
||||
"replace": {
|
||||
"typo3-ter/yoast-seo": "self.version"
|
||||
},
|
||||
"require-dev": {
|
||||
"composer/class-map-generator": "^1.3.4",
|
||||
"dg/bypass-finals": "^1.8",
|
||||
"ergebnis/composer-normalize": "^2.43",
|
||||
"friendsofphp/php-cs-fixer": "^3.60.0",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.4",
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "^1.12 || ^2.1",
|
||||
"phpunit/phpunit": "^10.1 || ^11.2.5",
|
||||
"saschaegerer/phpstan-typo3": "^1.10 || ^2.1 || ^3.0.1",
|
||||
"typo3/coding-standards": "^0.7.1 || ^0.8.0",
|
||||
"typo3/tailor": "^1.7",
|
||||
"typo3/testing-framework": "^7.1.0 || ^8.2.0 || ^9.5.0"
|
||||
},
|
||||
"suggest": {
|
||||
"typo3/cms-dashboard": "Display Yoast SEO widgets within the Dashboard of TYPO3"
|
||||
},
|
||||
"type": "typo3-cms-extension",
|
||||
"extra": {
|
||||
"typo3/cms": {
|
||||
"web-dir": ".Build/public",
|
||||
"extension-key": "yoast_seo"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"YoastSeoForTypo3\\YoastSeo\\": "Classes/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"GPL-3.0-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Team Yoast",
|
||||
"email": "[email protected]",
|
||||
"homepage": "https://yoast.com"
|
||||
},
|
||||
{
|
||||
"name": "Team MaxServ",
|
||||
"email": "[email protected]",
|
||||
"homepage": "https://maxserv.com"
|
||||
}
|
||||
],
|
||||
"description": "Yoast SEO for TYPO3",
|
||||
"homepage": "https://yoast.com",
|
||||
"keywords": [
|
||||
"MaxServ",
|
||||
"TYPO3 CMS",
|
||||
"seo",
|
||||
"yoast"
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://docs.typo3.org/p/yoast-seo-for-typo3/yoast_seo/main/en-us/",
|
||||
"issues": "https://github.com/Yoast/Yoast-SEO-for-TYPO3/issues",
|
||||
"source": "https://github.com/Yoast/Yoast-SEO-for-TYPO3"
|
||||
},
|
||||
"time": "2026-07-08T13:20:01+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
|
||||
@@ -94,6 +94,10 @@ $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['rootline']
|
||||
];
|
||||
unset($redisOptions);
|
||||
|
||||
// Favicon sets from realfavicongenerator.net (fileadmin/user_upload/favicon/<site>/) contain an ICO
|
||||
// and a web manifest, which TYPO3 13 rejects on upload unless an extension list allows them
|
||||
$GLOBALS['TYPO3_CONF_VARS']['SYS']['miscfile_ext'] .= ',ico,webmanifest';
|
||||
|
||||
// Deployer creates an empty secrets.php if none exists yet: only an array counts
|
||||
$secrets = is_file(__DIR__ . '/secrets.php') ? require __DIR__ . '/secrets.php' : null;
|
||||
if (is_array($secrets)) {
|
||||
|
||||
@@ -2,29 +2,16 @@
|
||||
|
||||
namespace Deployer;
|
||||
|
||||
// Run on the host (Deployer 8, PHP >= 8.3): dep deploy prod. The SSH keys stay on the host; the
|
||||
// build runs inside DDEV, so Composer and Node are the project's versions.
|
||||
// Prerequisites on the host: see .ddev/plans/TYPO3-13-GO-LIVE.md (PHP 8.5.12, database, secrets.php)
|
||||
|
||||
require 'recipe/typo3.php';
|
||||
require 'contrib/rsync.php';
|
||||
require 'contrib/cachetool.php';
|
||||
|
||||
set('cachetool_url', 'https://github.com/gordalina/cachetool/releases/download/10.0.0/cachetool.phar');
|
||||
|
||||
set('application', 'ep-reisen-typo3-13');
|
||||
|
||||
// Defined here rather than taken from recipe/typo3.php, whose task and setting names differ between
|
||||
// Deployer versions (a globally installed "dep" may not be the project's vendor/bin/dep 8)
|
||||
set('typo3/public_dir', 'public');
|
||||
set('bin/typo3', 'vendor/bin/typo3');
|
||||
set('keep_releases', 3);
|
||||
|
||||
// The release is built locally from the committed state, so nothing uncommitted is ever deployed
|
||||
// and the host needs neither Composer nor Node
|
||||
set('build_dir', __DIR__ . '/var/deploy-build');
|
||||
set('use_rsync', true);
|
||||
set('rsync_src', '{{build_dir}}');
|
||||
|
||||
// fileadmin is the production fileadmin of the TYPO3 10 release: it is the CDN origin's fileadmin
|
||||
// (static/ep-reisen/fileadmin links there too), and TYPO3 13 writes its processed images into it
|
||||
// fileadmin of the TYPO3 10 release until it is moved into shared/ (plan 4a, tidy up step 2)
|
||||
set('fileadmin_path', '/usr/home/eptypo3/public_html/ep-reisen-typo3/shared/public/fileadmin');
|
||||
|
||||
set('shared_dirs', [
|
||||
@@ -36,10 +23,7 @@ set('shared_dirs', [
|
||||
// Baseline of the MyE&P import: without it every deploy would trigger a full re-import
|
||||
'var/transient/ep_products_import',
|
||||
]);
|
||||
// settings.php is shared as LocalConfiguration.php was on TYPO3 10: production is leading, so what
|
||||
// is changed in the backend (extension configuration, install tool) survives deploys and rollbacks.
|
||||
// It is not in git (encryptionKey, install tool password): configuration changes for production are
|
||||
// made there, in the backend or by hand on the shared file.
|
||||
// Not in git, production is leading (encryptionKey, install tool, backend changes)
|
||||
set('shared_files', [
|
||||
'config/system/secrets.php',
|
||||
'config/system/settings.php',
|
||||
@@ -53,6 +37,13 @@ set('writable_dirs', [
|
||||
]);
|
||||
set('writable_mode', 'chmod');
|
||||
|
||||
// The release is built from the committed state, so nothing uncommitted and no dev dependencies go live
|
||||
set('build_dir', __DIR__ . '/var/deploy-build');
|
||||
set('use_rsync', true);
|
||||
set('rsync_src', '{{build_dir}}');
|
||||
|
||||
// contrib/rsync.php replaces the TYPO3 recipe's rsync settings, so its exclude list (which has var/)
|
||||
// does not apply: the language packs in var/labels are deployed with the release
|
||||
$rsync = get('rsync');
|
||||
$rsync['exclude'] = array_merge($rsync['exclude'], [
|
||||
'/{{typo3/public_dir}}/fileadmin',
|
||||
@@ -68,7 +59,7 @@ $rsync['exclude'] = array_merge($rsync['exclude'], [
|
||||
'/package-lock.json',
|
||||
'/.nvmrc',
|
||||
]);
|
||||
// The build directory has no .gitignore filtering to do, and the filter would drop the built assets
|
||||
// No .gitignore filter: it would drop the built assets
|
||||
$rsync['filter'] = [];
|
||||
// -t preserves mtimes: without it every file lands with a fresh timestamp, so unchanged
|
||||
// files get a new Last-Modified on every deploy and every conditional request revalidates
|
||||
@@ -83,124 +74,45 @@ host('prod')
|
||||
->setForwardAgent(true)
|
||||
->setSshMultiplexing(true)
|
||||
->setDeployPath('/usr/home/eptypo3/public_html/{{application}}')
|
||||
// Verify on the host once Hetzner has installed it
|
||||
->set('bin/php', '/usr/bin/php85')
|
||||
->set('http_user', 'eptypo3')
|
||||
// The temp script goes into the shared typo3temp/assets, which resolves to the same directory from
|
||||
// every release: PHP workers with a stale realpath cache still map "current" to the previous release
|
||||
// and would 404 on a script placed inside the new one.
|
||||
->set('cachetool_args', '--web=SymfonyHttpClient --web-path={{deploy_path}}/shared/{{typo3/public_dir}}/typo3temp/assets/ --web-url=https://www.ep-reisen.de/typo3temp/assets')
|
||||
;
|
||||
|
||||
desc('Build the release locally: committed state, production dependencies, theme assets');
|
||||
task('build', function () {
|
||||
// Inside DDEV directly, on the host through "ddev exec" (paths relative to the project root)
|
||||
$inDdev = getenv('IS_DDEV_PROJECT') === 'true';
|
||||
$exec = fn(string $command) => runLocally($inDdev
|
||||
? $command
|
||||
: 'ddev exec bash -c ' . escapeshellarg($command));
|
||||
task('deploy:build', function () {
|
||||
runLocally('rm -rf {{build_dir}} && mkdir -p {{build_dir}}');
|
||||
runLocally('git archive HEAD | tar -x -C {{build_dir}}');
|
||||
// Assets first: Composer only publishes an extension's Resources/Public as public/_assets/<hash>
|
||||
// if the directory exists when it runs, and the theme's is created by the build
|
||||
$exec('cd var/deploy-build && npm ci --no-audit --no-fund && npm run build');
|
||||
$exec('cd var/deploy-build && composer install --no-dev --prefer-dist --no-progress --no-interaction --optimize-autoloader');
|
||||
runLocally('test -L {{build_dir}}/public/_assets/' . md5('/vendor/ep/ep-theme/') . ' && test -f {{build_dir}}/packages/ep_theme/Resources/Public/entrypoints.json');
|
||||
// Assets first: Composer only publishes the theme's Resources/Public to public/_assets
|
||||
// if the directory exists when it runs, and the asset build creates it
|
||||
runLocally('ddev exec bash -c "cd var/deploy-build && npm ci --no-audit --no-fund && npm run build"');
|
||||
runLocally('ddev exec bash -c "cd var/deploy-build && composer install --no-dev --prefer-dist --no-progress --no-interaction --optimize-autoloader"');
|
||||
})->once();
|
||||
|
||||
desc('Read-only checks of the host before the first deploy (see .ddev/plans/TYPO3-13-GO-LIVE.md)');
|
||||
task('host:check', function () {
|
||||
$checks = [
|
||||
'PHP CLI 8.5.12+' => '{{bin/php}} -r \'exit(version_compare(PHP_VERSION, "8.5.12", ">=") ? 0 : 1);\' && {{bin/php}} -v | head -1',
|
||||
'PHP extensions' => '{{bin/php}} -r \'$m = array_diff(["mysqli", "pdo_mysql", "intl", "mbstring", "xml", "zip", "gd", "fileinfo", "openssl", "curl", "zlib"], get_loaded_extensions()); echo $m ? "missing: " . implode(", ", $m) : "ok"; exit($m ? 1 : 0);\'',
|
||||
'image processor (GraphicsMagick)' => 'test -x /usr/bin/gm && /usr/bin/gm version | head -1',
|
||||
'production fileadmin' => 'test -d {{fileadmin_path}} && du -sh {{fileadmin_path}} 2>/dev/null | cut -f1',
|
||||
'static/ep-reisen/fileadmin links there' => 'test "$(readlink -f /usr/home/eptypo3/public_html/static/ep-reisen/fileadmin)" = "$(readlink -f {{fileadmin_path}})" && echo yes',
|
||||
'free disk space' => 'df -h /usr/home/eptypo3 | tail -1',
|
||||
'secrets.php in place' => 'test -s {{deploy_path}}/shared/config/system/secrets.php && {{bin/php}} -r \'exit(is_array(require "{{deploy_path}}/shared/config/system/secrets.php") ? 0 : 1);\' && echo yes',
|
||||
'MyE&P reachable' => 'curl -s -o /dev/null -w "%{http_code}" --max-time 10 https://my.ep-reisen.de/api/last-update',
|
||||
];
|
||||
$failed = false;
|
||||
foreach ($checks as $label => $command) {
|
||||
try {
|
||||
writeln(sprintf('<info>✔</info> %s: %s', $label, trim(run($command))));
|
||||
} catch (\Throwable $e) {
|
||||
writeln(sprintf('<error>✘</error> %s', $label));
|
||||
$failed = true;
|
||||
}
|
||||
}
|
||||
writeln('Not checkable from the CLI: open_basedir and PHP 8.5.12 (FPM) of the static vhosts, see the go-live plan.');
|
||||
if ($failed) {
|
||||
throw new \RuntimeException('Host checks failed');
|
||||
}
|
||||
task('typo3:fileadmin', function () {
|
||||
// Relative (-r), like Deployer's shared dirs: the vhosts answer 403 for an absolute symlink here
|
||||
run('ln -sfnr {{fileadmin_path}} {{release_path}}/{{typo3/public_dir}}/fileadmin');
|
||||
});
|
||||
|
||||
desc('Put the secrets.php template into shared/ unless a secrets.php is there already (never overwrites)');
|
||||
task('typo3:secrets:init', function () {
|
||||
$target = '{{deploy_path}}/shared/config/system/secrets.php';
|
||||
if (test("[ -s $target ]")) {
|
||||
return;
|
||||
}
|
||||
run('mkdir -p {{deploy_path}}/shared/config/system');
|
||||
upload(__DIR__ . '/config/system/secrets.example.php', $target);
|
||||
run("chmod 600 $target");
|
||||
writeln('<comment>Created ' . parse($target) . ' from the template: fill it in, then deploy again.</comment>');
|
||||
});
|
||||
|
||||
desc('Seed the shared settings.php from the live release unless it is there already (never overwrites)');
|
||||
task('typo3:settings:init', function () {
|
||||
$target = '{{deploy_path}}/shared/config/system/settings.php';
|
||||
if (test("[ -s $target ]")) {
|
||||
return;
|
||||
}
|
||||
// deploy:shared would seed it from the new release, i.e. from git, and drop production's settings
|
||||
if (!test('[ -f {{deploy_path}}/current/config/system/settings.php ]')) {
|
||||
return;
|
||||
}
|
||||
run('mkdir -p {{deploy_path}}/shared/config/system');
|
||||
run("cp -L {{deploy_path}}/current/config/system/settings.php $target");
|
||||
writeln('<comment>Created ' . parse($target) . ' from the live release.</comment>');
|
||||
});
|
||||
|
||||
desc('Stop before the database is touched while secrets.php still lacks the database connection');
|
||||
task('typo3:secrets:check', function () {
|
||||
$secrets = '{{deploy_path}}/shared/config/system/secrets.php';
|
||||
$filled = run("{{bin/php}} -r '\$s = require \"$secrets\"; echo is_array(\$s) && (\$s[\"DB\"][\"Connections\"][\"Default\"][\"dbname\"] ?? \"\") !== \"\" ? \"yes\" : \"no\";'");
|
||||
if ($filled !== 'yes') {
|
||||
throw new \RuntimeException(parse("$secrets has no database connection yet: fill it in, then deploy again. Nothing went live."));
|
||||
}
|
||||
});
|
||||
|
||||
desc('TYPO3 - Set up all extensions (database schema: adds and changes only)');
|
||||
task('typo3:extension:setup', function () {
|
||||
run('{{bin/php}} {{release_path}}/{{bin/typo3}} extension:setup');
|
||||
});
|
||||
|
||||
desc('TYPO3 - Clear all caches');
|
||||
// current_path instead of the recipe's release_path, so it also works after a rollback
|
||||
task('typo3:cache:flush', function () {
|
||||
run('{{bin/php}} {{current_path}}/{{bin/typo3}} cache:flush');
|
||||
});
|
||||
|
||||
desc('Link the production fileadmin into the release');
|
||||
task('typo3:fileadmin', function () {
|
||||
run('test -d {{fileadmin_path}}');
|
||||
// Relative (-r), like Deployer's shared dirs: the vhosts answer 403 for an absolute symlink here
|
||||
run('ln -sfnr {{fileadmin_path}} {{release_path}}/{{typo3/public_dir}}/fileadmin');
|
||||
run('test -d {{release_path}}/{{typo3/public_dir}}/fileadmin/user_upload');
|
||||
});
|
||||
|
||||
desc('Deploys TYPO3 13');
|
||||
task('deploy', [
|
||||
'deploy:info',
|
||||
// Build first, so a failing build aborts before the server is touched at all.
|
||||
'build',
|
||||
// Build locally first, so a failing build aborts before the server is touched at all.
|
||||
'deploy:build',
|
||||
'deploy:setup',
|
||||
'deploy:lock',
|
||||
'deploy:release',
|
||||
'rsync',
|
||||
'typo3:secrets:init',
|
||||
'typo3:settings:init',
|
||||
'deploy:shared',
|
||||
'typo3:fileadmin',
|
||||
'deploy:writable',
|
||||
'typo3:secrets:check',
|
||||
// The schema has to exist before the new code starts serving traffic (adds and changes only).
|
||||
// The schema has to exist before the new code starts serving traffic.
|
||||
'typo3:extension:setup',
|
||||
// deploy:publish == deploy:symlink, deploy:unlock, deploy:cleanup, deploy:success
|
||||
'deploy:publish',
|
||||
@@ -209,12 +121,10 @@ task('deploy', [
|
||||
// Caches belong to the release that goes live, so they are cleared after the symlink flip. Hooking
|
||||
// into deploy:symlink rather than appending to the list above keeps them inside deploy:publish, ahead
|
||||
// of deploy:unlock and deploy:success - a failing cache task must not follow a declared success.
|
||||
// No OPcache reset (cachetool): its web adapter would need PHP under a host's typo3temp. Vhosts that
|
||||
// point at current/public keep running the previous release until PHP's path cache expires (~2 min);
|
||||
// pages it renders in that window stay in the page cache until the next flush.
|
||||
// OPcache first: until it is reset the vhosts keep running the previous release, and the pages it
|
||||
// renders (with its hashed CSS/JS) would outlive the flush.
|
||||
after('deploy:symlink', 'cachetool:clear:opcache');
|
||||
after('deploy:symlink', 'typo3:cache:flush');
|
||||
// A rollback switches the code back; pages cached by the other release must not survive it
|
||||
// Pages cached by the other release must not survive a rollback
|
||||
after('rollback', 'cachetool:clear:opcache');
|
||||
after('rollback', 'typo3:cache:flush');
|
||||
|
||||
|
||||
after('deploy:failed', 'deploy:unlock');
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace EP\EpProducts\Controller;
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2016 Björn Fromme <[email protected]>, dreipunktnull
|
||||
*
|
||||
* 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 EP\EpProducts\Domain\Model\Dto\NewsletterSubscriptionRequest;
|
||||
use EP\EpProducts\MyEP\ApiClient;
|
||||
use EP\EpProducts\MyEP\ApiException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
|
||||
|
||||
class NewsletterController extends ActionController
|
||||
{
|
||||
private ApiClient $apiClient;
|
||||
|
||||
public function __construct(ApiClient $apiClient)
|
||||
{
|
||||
$this->apiClient = $apiClient;
|
||||
}
|
||||
|
||||
public function subscriptionFormAction(?NewsletterSubscriptionRequest $subscriptionRequest = null): ResponseInterface
|
||||
{
|
||||
if (null === $subscriptionRequest) {
|
||||
$subscriptionRequest = new NewsletterSubscriptionRequest();
|
||||
}
|
||||
|
||||
try {
|
||||
$lists = $this->apiClient->getNewsletterLists();
|
||||
} catch (ApiException $e) {
|
||||
$lists = [];
|
||||
}
|
||||
|
||||
$this->view->assign('subscriptionRequest', $subscriptionRequest);
|
||||
$this->view->assign('lists', $lists);
|
||||
|
||||
return $this->htmlResponse();
|
||||
}
|
||||
|
||||
public function subscriptionFormSubmitAction(NewsletterSubscriptionRequest $subscriptionRequest): ResponseInterface
|
||||
{
|
||||
try {
|
||||
$result = $this->apiClient->subscribeToNewsletters($subscriptionRequest);
|
||||
$result['success'] = true;
|
||||
} catch (ApiException $e) {
|
||||
$result = [
|
||||
'success' => false,
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
|
||||
$this->view->assign('result', $result);
|
||||
|
||||
return $this->htmlResponse();
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,8 @@
|
||||
<foreign_table_where>ORDER BY name</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0"/>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label/>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
@@ -37,8 +37,8 @@
|
||||
<foreign_table_where>ORDER BY name</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0"/>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label/>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
@@ -53,12 +53,12 @@
|
||||
<renderType>selectSingle</renderType>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Winter</numIndex>
|
||||
<numIndex index="1">w</numIndex>
|
||||
<label>Winter</label>
|
||||
<value>w</value>
|
||||
</numIndex>
|
||||
<numIndex index="1" type="array">
|
||||
<numIndex index="0">Sommer</numIndex>
|
||||
<numIndex index="1">s</numIndex>
|
||||
<label>Sommer</label>
|
||||
<value>s</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>1</minitems>
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
<foreign_table_where>AND tx_epproducts_domain_model_concept.hidden = 0 AND tx_epproducts_domain_model_concept.deleted = 0 ORDER BY tx_epproducts_domain_model_concept.name</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Alle</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Alle</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>1</minitems>
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
<foreign_table_where>AND tx_epproducts_domain_model_country.hidden = 0 AND tx_epproducts_domain_model_country.deleted = 0 ORDER BY tx_epproducts_domain_model_country.name</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0"/>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label/>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
<foreign_table_where>AND tx_epproducts_domain_model_hotel.hidden = 0 AND tx_epproducts_domain_model_hotel.deleted = 0 ORDER BY tx_epproducts_domain_model_hotel.name</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Alle</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Alle</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
|
||||
@@ -31,8 +31,8 @@
|
||||
<foreign_table_where>AND tx_epproducts_domain_model_hotel.hidden = 0 AND tx_epproducts_domain_model_hotel.deleted = 0 ORDER BY tx_epproducts_domain_model_hotel.name</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Alle</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Alle</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>1</minitems>
|
||||
|
||||
@@ -17,16 +17,16 @@
|
||||
<renderType>selectSingle</renderType>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">vierspaltig</numIndex>
|
||||
<numIndex index="1">4</numIndex>
|
||||
<label>vierspaltig</label>
|
||||
<value>4</value>
|
||||
</numIndex>
|
||||
<numIndex index="1" type="array">
|
||||
<numIndex index="0">dreispaltig</numIndex>
|
||||
<numIndex index="1">3</numIndex>
|
||||
<label>dreispaltig</label>
|
||||
<value>3</value>
|
||||
</numIndex>
|
||||
<numIndex index="2" type="array">
|
||||
<numIndex index="0">zweispaltig</numIndex>
|
||||
<numIndex index="1">2</numIndex>
|
||||
<label>zweispaltig</label>
|
||||
<value>2</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>1</minitems>
|
||||
@@ -44,8 +44,8 @@
|
||||
<foreign_table_where>ORDER BY name</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Keine Zuordnung</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Keine Zuordnung</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
@@ -63,8 +63,8 @@
|
||||
<foreign_table_where>ORDER BY name</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Keine Zuordnung</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Keine Zuordnung</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
@@ -82,8 +82,8 @@
|
||||
<foreign_table_where>ORDER BY name</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Keine Zuordnung</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Keine Zuordnung</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
@@ -100,8 +100,8 @@
|
||||
<foreign_table_where>ORDER BY name</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Keine Zuordnung</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Keine Zuordnung</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
@@ -118,8 +118,8 @@
|
||||
<foreign_table_where>ORDER BY name_internal</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Keine Zuordnung</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Keine Zuordnung</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
@@ -134,28 +134,28 @@
|
||||
<renderType>selectSingle</renderType>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Alle</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Alle</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
<numIndex index="1" type="array">
|
||||
<numIndex index="0">Standard</numIndex>
|
||||
<numIndex index="1">1</numIndex>
|
||||
<label>Standard</label>
|
||||
<value>1</value>
|
||||
</numIndex>
|
||||
<numIndex index="2" type="array">
|
||||
<numIndex index="0">Basic</numIndex>
|
||||
<numIndex index="1">5</numIndex>
|
||||
<label>Basic</label>
|
||||
<value>5</value>
|
||||
</numIndex>
|
||||
<numIndex index="3" type="array">
|
||||
<numIndex index="0">Komfort</numIndex>
|
||||
<numIndex index="1">2</numIndex>
|
||||
<label>Komfort</label>
|
||||
<value>2</value>
|
||||
</numIndex>
|
||||
<numIndex index="4" type="array">
|
||||
<numIndex index="0">Deluxe</numIndex>
|
||||
<numIndex index="1">3</numIndex>
|
||||
<label>Deluxe</label>
|
||||
<value>3</value>
|
||||
</numIndex>
|
||||
<numIndex index="5" type="array">
|
||||
<numIndex index="0">Superdeluxe</numIndex>
|
||||
<numIndex index="1">4</numIndex>
|
||||
<label>Superdeluxe</label>
|
||||
<value>4</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
@@ -169,24 +169,24 @@
|
||||
<renderType>selectCheckBox</renderType>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Ferienwohnung</numIndex>
|
||||
<numIndex index="1">1</numIndex>
|
||||
<label>Ferienwohnung</label>
|
||||
<value>1</value>
|
||||
</numIndex>
|
||||
<numIndex index="1" type="array">
|
||||
<numIndex index="0">Sportclub</numIndex>
|
||||
<numIndex index="1">2</numIndex>
|
||||
<label>Sportclub</label>
|
||||
<value>2</value>
|
||||
</numIndex>
|
||||
<numIndex index="2" type="array">
|
||||
<numIndex index="0">Apartment</numIndex>
|
||||
<numIndex index="1">3</numIndex>
|
||||
<label>Apartment</label>
|
||||
<value>3</value>
|
||||
</numIndex>
|
||||
<numIndex index="3" type="array">
|
||||
<numIndex index="0">Gästerhaus</numIndex>
|
||||
<numIndex index="1">4</numIndex>
|
||||
<label>Gästerhaus</label>
|
||||
<value>4</value>
|
||||
</numIndex>
|
||||
<numIndex index="4" type="array">
|
||||
<numIndex index="0">Pension</numIndex>
|
||||
<numIndex index="1">5</numIndex>
|
||||
<label>Pension</label>
|
||||
<value>5</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
|
||||
@@ -17,16 +17,16 @@
|
||||
<renderType>selectSingle</renderType>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">vierspaltig</numIndex>
|
||||
<numIndex index="1">4</numIndex>
|
||||
<label>vierspaltig</label>
|
||||
<value>4</value>
|
||||
</numIndex>
|
||||
<numIndex index="1" type="array">
|
||||
<numIndex index="0">dreispaltig</numIndex>
|
||||
<numIndex index="1">3</numIndex>
|
||||
<label>dreispaltig</label>
|
||||
<value>3</value>
|
||||
</numIndex>
|
||||
<numIndex index="2" type="array">
|
||||
<numIndex index="0">zweispaltig</numIndex>
|
||||
<numIndex index="1">2</numIndex>
|
||||
<label>zweispaltig</label>
|
||||
<value>2</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>1</minitems>
|
||||
@@ -44,8 +44,8 @@
|
||||
<foreign_table_where>ORDER BY name</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Keine Zuordnung</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Keine Zuordnung</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
@@ -63,8 +63,8 @@
|
||||
<foreign_table_where>ORDER BY name</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Keine Zuordnung</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Keine Zuordnung</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
@@ -81,8 +81,8 @@
|
||||
<foreign_table_where>ORDER BY name_internal</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Keine Zuordnung</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Keine Zuordnung</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
@@ -97,28 +97,28 @@
|
||||
<renderType>selectSingle</renderType>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Alle</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Alle</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
<numIndex index="1" type="array">
|
||||
<numIndex index="0">Standard</numIndex>
|
||||
<numIndex index="1">1</numIndex>
|
||||
<label>Standard</label>
|
||||
<value>1</value>
|
||||
</numIndex>
|
||||
<numIndex index="2" type="array">
|
||||
<numIndex index="0">Basic</numIndex>
|
||||
<numIndex index="1">5</numIndex>
|
||||
<label>Basic</label>
|
||||
<value>5</value>
|
||||
</numIndex>
|
||||
<numIndex index="3" type="array">
|
||||
<numIndex index="0">Komfort</numIndex>
|
||||
<numIndex index="1">2</numIndex>
|
||||
<label>Komfort</label>
|
||||
<value>2</value>
|
||||
</numIndex>
|
||||
<numIndex index="4" type="array">
|
||||
<numIndex index="0">Deluxe</numIndex>
|
||||
<numIndex index="1">3</numIndex>
|
||||
<label>Deluxe</label>
|
||||
<value>3</value>
|
||||
</numIndex>
|
||||
<numIndex index="5" type="array">
|
||||
<numIndex index="0">Superdeluxe</numIndex>
|
||||
<numIndex index="1">4</numIndex>
|
||||
<label>Superdeluxe</label>
|
||||
<value>4</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
@@ -132,24 +132,24 @@
|
||||
<renderType>selectCheckBox</renderType>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Ferienwohnung</numIndex>
|
||||
<numIndex index="1">1</numIndex>
|
||||
<label>Ferienwohnung</label>
|
||||
<value>1</value>
|
||||
</numIndex>
|
||||
<numIndex index="1" type="array">
|
||||
<numIndex index="0">Sportclub</numIndex>
|
||||
<numIndex index="1">2</numIndex>
|
||||
<label>Sportclub</label>
|
||||
<value>2</value>
|
||||
</numIndex>
|
||||
<numIndex index="2" type="array">
|
||||
<numIndex index="0">Apartment</numIndex>
|
||||
<numIndex index="1">3</numIndex>
|
||||
<label>Apartment</label>
|
||||
<value>3</value>
|
||||
</numIndex>
|
||||
<numIndex index="3" type="array">
|
||||
<numIndex index="0">Gästerhaus</numIndex>
|
||||
<numIndex index="1">4</numIndex>
|
||||
<label>Gästerhaus</label>
|
||||
<value>4</value>
|
||||
</numIndex>
|
||||
<numIndex index="4" type="array">
|
||||
<numIndex index="0">Pension</numIndex>
|
||||
<numIndex index="1">5</numIndex>
|
||||
<label>Pension</label>
|
||||
<value>5</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
<default>Pricetable->event</default>
|
||||
<items type="array">
|
||||
<numIndex index="1" type="array">
|
||||
<numIndex index="0">Preistabelle Eventreise</numIndex>
|
||||
<numIndex index="1">Pricetable->event</numIndex>
|
||||
<label>Preistabelle Eventreise</label>
|
||||
<value>Pricetable->event</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
</config>
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
<foreign_table_where>AND tx_epproducts_domain_model_product.hidden = 0 AND tx_epproducts_domain_model_product.deleted = 0 ORDER BY tx_epproducts_domain_model_product.name_internal</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Alle</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Alle</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
@@ -37,8 +37,8 @@
|
||||
<foreign_table_where>AND tx_epproducts_domain_model_hotel.hidden = 0 AND tx_epproducts_domain_model_hotel.deleted = 0 ORDER BY tx_epproducts_domain_model_hotel.name</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Alle</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Alle</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
|
||||
@@ -31,8 +31,8 @@
|
||||
<foreign_table_where>AND tx_epproducts_domain_model_hotel.hidden = 0 AND tx_epproducts_domain_model_hotel.deleted = 0 ORDER BY tx_epproducts_domain_model_hotel.name</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Alle</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Alle</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>1</minitems>
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
<default>Product->teasergroup</default>
|
||||
<items type="array">
|
||||
<numIndex index="1" type="array">
|
||||
<numIndex index="0">Teasergruppe</numIndex>
|
||||
<numIndex index="1">Product->teasergroup</numIndex>
|
||||
<label>Teasergruppe</label>
|
||||
<value>Product->teasergroup</value>
|
||||
</numIndex>
|
||||
<numIndex index="2" type="array">
|
||||
<numIndex index="0">Einzelteaser</numIndex>
|
||||
<numIndex index="1">Product->teaser</numIndex>
|
||||
<label>Einzelteaser</label>
|
||||
<value>Product->teaser</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
</config>
|
||||
@@ -40,8 +40,8 @@
|
||||
<foreign_table_where>ORDER BY name</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Keine Zuordnung</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Keine Zuordnung</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
@@ -60,8 +60,8 @@
|
||||
<foreign_table_where>ORDER BY name</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Keine Zuordnung</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Keine Zuordnung</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
@@ -80,8 +80,8 @@
|
||||
<foreign_table_where>ORDER BY name</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Keine Zuordnung</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Keine Zuordnung</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<size>5</size>
|
||||
@@ -98,8 +98,8 @@
|
||||
<foreign_table_where>ORDER BY name</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Alle</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Alle</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
@@ -147,8 +147,8 @@
|
||||
<foreign_table_where>ORDER BY name_internal</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Alle</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Alle</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
@@ -165,12 +165,12 @@
|
||||
<renderType>selectSingle</renderType>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Spalten</numIndex>
|
||||
<numIndex index="1">cols</numIndex>
|
||||
<label>Spalten</label>
|
||||
<value>cols</value>
|
||||
</numIndex>
|
||||
<numIndex index="1" type="array">
|
||||
<numIndex index="0">Reihen</numIndex>
|
||||
<numIndex index="1">rows</numIndex>
|
||||
<label>Reihen</label>
|
||||
<value>rows</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
</config>
|
||||
@@ -185,24 +185,24 @@
|
||||
<renderType>selectCheckBox</renderType>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Ferienwohnung</numIndex>
|
||||
<numIndex index="1">1</numIndex>
|
||||
<label>Ferienwohnung</label>
|
||||
<value>1</value>
|
||||
</numIndex>
|
||||
<numIndex index="1" type="array">
|
||||
<numIndex index="0">Sportclub</numIndex>
|
||||
<numIndex index="1">2</numIndex>
|
||||
<label>Sportclub</label>
|
||||
<value>2</value>
|
||||
</numIndex>
|
||||
<numIndex index="2" type="array">
|
||||
<numIndex index="0">Apartment</numIndex>
|
||||
<numIndex index="1">3</numIndex>
|
||||
<label>Apartment</label>
|
||||
<value>3</value>
|
||||
</numIndex>
|
||||
<numIndex index="3" type="array">
|
||||
<numIndex index="0">Gästehaus</numIndex>
|
||||
<numIndex index="1">4</numIndex>
|
||||
<label>Gästehaus</label>
|
||||
<value>4</value>
|
||||
</numIndex>
|
||||
<numIndex index="4" type="array">
|
||||
<numIndex index="0">Pension</numIndex>
|
||||
<numIndex index="1">5</numIndex>
|
||||
<label>Pension</label>
|
||||
<value>5</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
@@ -228,8 +228,8 @@
|
||||
<foreign_table_where>ORDER BY title</foreign_table_where>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Default</numIndex>
|
||||
<numIndex index="1">0</numIndex>
|
||||
<label>Default</label>
|
||||
<value>0</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>0</minitems>
|
||||
|
||||
@@ -29,12 +29,12 @@
|
||||
<renderType>selectSingle</renderType>
|
||||
<items type="array">
|
||||
<numIndex index="0" type="array">
|
||||
<numIndex index="0">Winter</numIndex>
|
||||
<numIndex index="1">w</numIndex>
|
||||
<label>Winter</label>
|
||||
<value>w</value>
|
||||
</numIndex>
|
||||
<numIndex index="1" type="array">
|
||||
<numIndex index="0">Sommer</numIndex>
|
||||
<numIndex index="1">s</numIndex>
|
||||
<label>Sommer</label>
|
||||
<value>s</value>
|
||||
</numIndex>
|
||||
</items>
|
||||
<minitems>1</minitems>
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
<config>
|
||||
<type>select</type>
|
||||
<renderType>selectMultipleSideBySide</renderType>
|
||||
<enableMultiSelectFilterTextfield>1</enableMultiSelectFilterTextfield>
|
||||
<foreign_table>sys_category</foreign_table>
|
||||
<minitems>0</minitems>
|
||||
<maxitems>99</maxitems>
|
||||
|
||||
@@ -127,6 +127,12 @@ call_user_func(function () {
|
||||
'FAQ'
|
||||
);
|
||||
|
||||
ExtensionUtility::registerPlugin(
|
||||
'EpProducts',
|
||||
'newsletter_subscription',
|
||||
'Newsletter-/RA-Registrierung'
|
||||
);
|
||||
|
||||
ExtensionUtility::registerPlugin(
|
||||
'EpProducts',
|
||||
'maps',
|
||||
|
||||
@@ -7,6 +7,7 @@ use EP\EpProducts\Controller\CountryController;
|
||||
use EP\EpProducts\Controller\FaqController;
|
||||
use EP\EpProducts\Controller\HotelController;
|
||||
use EP\EpProducts\Controller\MapController;
|
||||
use EP\EpProducts\Controller\NewsletterController;
|
||||
use EP\EpProducts\Controller\PricetableController;
|
||||
use EP\EpProducts\Controller\RegionController;
|
||||
use EP\EpProducts\Controller\TeamController;
|
||||
@@ -174,6 +175,17 @@ $boot = function () {
|
||||
]
|
||||
);
|
||||
|
||||
ExtensionUtility::configurePlugin(
|
||||
'EpProducts',
|
||||
'newsletter_subscription',
|
||||
[
|
||||
NewsletterController::class => 'subscriptionForm,subscriptionFormSubmit',
|
||||
],
|
||||
[
|
||||
NewsletterController::class => 'subscriptionForm,subscriptionFormSubmit',
|
||||
]
|
||||
);
|
||||
|
||||
ExtensionUtility::configurePlugin(
|
||||
'EpProducts',
|
||||
'maps',
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
use TYPO3\CMS\Core\Security\ContentSecurityPolicy\Directive;
|
||||
use TYPO3\CMS\Core\Security\ContentSecurityPolicy\Mutation;
|
||||
use TYPO3\CMS\Core\Security\ContentSecurityPolicy\MutationCollection;
|
||||
use TYPO3\CMS\Core\Security\ContentSecurityPolicy\MutationMode;
|
||||
use TYPO3\CMS\Core\Security\ContentSecurityPolicy\Scope;
|
||||
use TYPO3\CMS\Core\Security\ContentSecurityPolicy\UriValue;
|
||||
use TYPO3\CMS\Core\Type\Map;
|
||||
|
||||
// The frontend references favicons and images on the CDN, and backend previews (yoast's snippet
|
||||
// preview) show them as they are.
|
||||
return Map::fromEntries([
|
||||
Scope::backend(),
|
||||
new MutationCollection(
|
||||
new Mutation(MutationMode::Extend, Directive::ImgSrc, new UriValue('https://cdn.ep-reisen.de')),
|
||||
),
|
||||
]);
|
||||
@@ -1,7 +1,6 @@
|
||||
# Retired 2026-10-24 (newsletter form and subscription, reseller export, group price calculator, which
|
||||
# Retired 2026-10-24 (newsletter form, reseller export, group price calculator, which
|
||||
# MyE&P replaced): the elements stay in the database and render nothing; the old code is in a46918d
|
||||
# should they come back
|
||||
tt_content.nlform = TEXT
|
||||
tt_content.list.20.epproducts_newsletter_subscription = TEXT
|
||||
tt_content.list.20.epproducts_reseller = TEXT
|
||||
tt_content.list.20.epproducts_hotel_groups_price = TEXT
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
plugin.tx_form.view {
|
||||
templateRootPaths.10 = EXT:ep_theme/Resources/Private/Templates/Form/
|
||||
# Spinner.html for Render.html
|
||||
partialRootPaths.10 = EXT:ep_theme/Resources/Private/Partials/Form/
|
||||
# Form/Island.html for Render.html
|
||||
partialRootPaths.10 = EXT:ep_theme/Resources/Private/Partials/
|
||||
}
|
||||
|
||||
plugin.tx_form.settings.yamlConfigurations {
|
||||
|
||||
@@ -4,6 +4,7 @@ page {
|
||||
viewport = width=device-width, initial-scale=1
|
||||
X-UA-Compatible = ie=edge
|
||||
format-detection = telephone=no
|
||||
google-site-verification = {$plugin.tx_eptheme.settings.googleSiteVerification}
|
||||
}
|
||||
|
||||
bodyTagCObject = COA
|
||||
@@ -40,32 +41,17 @@ page {
|
||||
headerData.100 = TEXT
|
||||
headerData.100.value = <link rel="preconnect" href="https://cdn.ep-reisen.de">
|
||||
|
||||
# The set realfavicongenerator.net generates (2024): what current browsers use, nothing for
|
||||
# outdated ones. faviconPath is the folder in fileadmin it was uploaded to.
|
||||
headerData.333 = TEXT
|
||||
headerData.333.value (
|
||||
<link rel="shortcut icon" type="image/x-icon" href="/{path:EXT:ep_theme/Resources/Public/images/favicon.ico}">
|
||||
<link rel="icon" type="image/x-icon" href="/{path:EXT:ep_theme/Resources/Public/images/favicon.ico}">
|
||||
<link rel="icon" type="image/gif" href="/{path:EXT:ep_theme/Resources/Public/images/favicon.gif}">
|
||||
<link rel="icon" type="image/png" href="/{path:EXT:ep_theme/Resources/Public/images/favicon.png}">
|
||||
<link rel="apple-touch-icon" href="/{path:EXT:ep_theme/Resources/Public/images/apple-touch-icon.png}">
|
||||
<link rel="apple-touch-icon" href="/{path:EXT:ep_theme/Resources/Public/images/apple-touch-icon-57x57.png}" sizes="57x57">
|
||||
<link rel="apple-touch-icon" href="/{path:EXT:ep_theme/Resources/Public/images/apple-touch-icon-60x60.png}" sizes="60x60">
|
||||
<link rel="apple-touch-icon" href="/{path:EXT:ep_theme/Resources/Public/images/apple-touch-icon-72x72.png}" sizes="72x72">
|
||||
<link rel="apple-touch-icon" href="/{path:EXT:ep_theme/Resources/Public/images/apple-touch-icon-76x76.png}" sizes="76x76">
|
||||
<link rel="apple-touch-icon" href="/{path:EXT:ep_theme/Resources/Public/images/apple-touch-icon-114x114.png}" sizes="114x114">
|
||||
<link rel="apple-touch-icon" href="/{path:EXT:ep_theme/Resources/Public/images/apple-touch-icon-120x120.png}" sizes="120x120">
|
||||
<link rel="apple-touch-icon" href="/{path:EXT:ep_theme/Resources/Public/images/apple-touch-icon-128x128.png}" sizes="128x128">
|
||||
<link rel="apple-touch-icon" href="/{path:EXT:ep_theme/Resources/Public/images/apple-touch-icon-144x144.png}" sizes="144x144">
|
||||
<link rel="apple-touch-icon" href="/{path:EXT:ep_theme/Resources/Public/images/apple-touch-icon-152x152.png}" sizes="152x152">
|
||||
<link rel="apple-touch-icon" href="/{path:EXT:ep_theme/Resources/Public/images/apple-touch-icon-180x180.png}" sizes="180x180">
|
||||
<link rel="apple-touch-icon" href="/{path:EXT:ep_theme/Resources/Public/images/apple-touch-icon-precomposed.png}">
|
||||
<link rel="icon" type="image/png" href="/{path:EXT:ep_theme/Resources/Public/images/favicon-16x16.png}" sizes="16x16">
|
||||
<link rel="icon" type="image/png" href="/{path:EXT:ep_theme/Resources/Public/images/favicon-32x32.png}" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/{path:EXT:ep_theme/Resources/Public/images/favicon-96x96.png}" sizes="96x96">
|
||||
<link rel="icon" type="image/png" href="/{path:EXT:ep_theme/Resources/Public/images/favicon-160x160.png}" sizes="160x160">
|
||||
<link rel="icon" type="image/png" href="/{path:EXT:ep_theme/Resources/Public/images/favicon-192x192.png}" sizes="192x192">
|
||||
<link rel="icon" type="image/png" href="/{path:EXT:ep_theme/Resources/Public/images/favicon-196x196.png}" sizes="196x196">
|
||||
<link rel="icon" type="image/png" href="/{$plugin.tx_eptheme.settings.faviconPath}/favicon-96x96.png" sizes="96x96" />
|
||||
<link rel="icon" type="image/svg+xml" href="/{$plugin.tx_eptheme.settings.faviconPath}/favicon.svg" />
|
||||
<link rel="shortcut icon" href="/{$plugin.tx_eptheme.settings.faviconPath}/favicon.ico" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/{$plugin.tx_eptheme.settings.faviconPath}/apple-touch-icon.png" />
|
||||
<meta name="apple-mobile-web-app-title" content="{$plugin.tx_eptheme.settings.faviconAppTitle}" />
|
||||
<link rel="manifest" href="/{$plugin.tx_eptheme.settings.faviconPath}/site.webmanifest" />
|
||||
)
|
||||
headerData.333.insertData = 1
|
||||
|
||||
# disableCompression keeps ResourceCompressor's hands off the Encore entries: Webpack
|
||||
# already minifies them, and copying them to typo3temp/assets/compressed only replaces the
|
||||
|
||||
@@ -129,6 +129,10 @@ plugin.tx_eptheme {
|
||||
defaultBodyclass = subpage
|
||||
# cat=eptheme/500/120; type=string; label=Logo image
|
||||
logoImage = EXT:ep_theme/Resources/Public/images/logo_wide.svg
|
||||
# cat=eptheme/500/125; type=string; label=Favicon folder (realfavicongenerator set, without leading/trailing slash)
|
||||
faviconPath = fileadmin/user_upload/favicon/ep
|
||||
# cat=eptheme/500/126; type=string; label=Home screen title (apple-mobile-web-app-title)
|
||||
faviconAppTitle = E&P Reisen und Events
|
||||
# cat=eptheme/500/130; type=string; label=Force active topnav uid
|
||||
forceActiveTopnavUid =
|
||||
# cat=eptheme/500/140; type=string; label=Booking URL template code
|
||||
@@ -166,6 +170,8 @@ plugin.tx_eptheme {
|
||||
googleMapsApiKey = AIzaSyDDOforD1O_j4xXy2nJybC2yQqbUAw9ClY
|
||||
# cat=eptheme/300/130; type=string; label=Canonical base URL/Domain
|
||||
canonicalBaseUrl = https://www.ep-reisen.de
|
||||
# cat=eptheme/300/140; type=string; label=Google site verification
|
||||
googleSiteVerification =
|
||||
|
||||
# cat=eptheme.events/700/100; type=string; label=Event date day from
|
||||
eventDateDayFrom =
|
||||
|
||||
@@ -76,9 +76,6 @@ plugin.tx_eptheme {
|
||||
globalConceptCode = {$plugin.tx_eptheme.settings.globalConceptCode}
|
||||
travelAlertPageUid = {$plugin.tx_eptheme.settings.travelAlertPageUid}
|
||||
myEpPageUid = {$plugin.tx_eptheme.settings.myEpPageUid}
|
||||
myEpApiEndpointUrl = {$plugin.tx_eptheme.settings.myEpApiEndpointUrl}
|
||||
myEpApiToken = {$plugin.tx_eptheme.settings.myEpApiToken}
|
||||
myEpApiTimeout = {$plugin.tx_eptheme.settings.myEpApiTimeout}
|
||||
facebookViewContentValues {
|
||||
productUid = {$plugin.tx_eptheme.settings.facebookViewContentProductUid}
|
||||
nameInternal = {$plugin.tx_eptheme.settings.facebookViewContentNameInternal}
|
||||
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 16 KiB |
@@ -2,7 +2,6 @@
|
||||
{
|
||||
"loaderUrl": "<f:format.raw>{f:uri.image(src: 'EXT:ep_theme/Resources/Public/images/ajax-loader-white.gif', absolute: 1)}</f:format.raw>",
|
||||
"iconSpriteUrl": "<f:format.raw>{f:uri.image(src: 'EXT:ep_theme/Resources/Public/images/icons_sprite.svg', absolute: 1)}</f:format.raw>",
|
||||
"myEpApiBaseUrl": "<f:format.raw>{settings.myEpApiEndpointUrl}</f:format.raw>",
|
||||
"paCode": <f:if condition='{context.paCode}'><f:then>"{context.paCode}"</f:then><f:else>null</f:else></f:if>,
|
||||
"externalDomains": <f:format.raw>{settings.domainsToTrack -> v:iterator.explode() -> f:format.json() -> f:format.raw()}</f:format.raw>
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
|
||||
<div class="form-island"{f:if(condition: id, then: ' id="{id}"')}>
|
||||
{content -> f:format.raw()}
|
||||
<div class="form-island__loading" aria-hidden="true">
|
||||
<f:render partial="Form/Spinner" arguments="{class: 'form-island__spinner'}" />
|
||||
</div>
|
||||
<style>
|
||||
.form-island { position: relative; }
|
||||
.form-island__loading { position: absolute; inset: 0; z-index: 10; display: flex; align-items: center; justify-content: center; background: rgb(255 255 255 / .7); visibility: hidden; opacity: 0; transition: opacity .15s, visibility .15s; }
|
||||
.form-island.htmx-request .form-island__loading { visibility: visible; opacity: 1; }
|
||||
.form-island__spinner { width: 6rem; height: 6rem; color: rgb(24 82 123); }
|
||||
.sbw .form-island__spinner { color: rgb(233 28 38); }
|
||||
.snz .form-island__spinner { color: rgb(249 195 61); }
|
||||
.suz .form-island__spinner { color: rgb(130 195 198); }
|
||||
.uch .form-island__spinner { color: rgb(25 163 220); }
|
||||
.ser .form-island__spinner { color: rgb(222 44 27); }
|
||||
</style>
|
||||
</div>
|
||||
</html>
|
||||
@@ -1,31 +1,10 @@
|
||||
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" xmlns:formvh="http://typo3.org/ns/TYPO3/CMS/Form/ViewHelpers" data-namespace-typo3-fluid="true">
|
||||
<f:comment>
|
||||
Every form sits in a .form-island, on pages TYPO3 13 renders as well as in the form page type
|
||||
(/path/form) that the static pages load: the form posts there, and htmx swaps the island as a
|
||||
whole (see Form.html). While a request runs, htmx sets htmx-request on it and the overlay
|
||||
covers the form. Styled here and not in the theme build: the static pages around the island
|
||||
load the CSS of the TYPO3 10 export. The spinner takes the button colour of each theme.
|
||||
</f:comment>
|
||||
<div class="form-island">
|
||||
<f:render partial="Form/Island" contentAs="content">
|
||||
<f:flashMessages />
|
||||
<f:if condition="{formConfiguration}">
|
||||
<div class="py-8">
|
||||
<formvh:render overrideConfiguration="{formConfiguration}" />
|
||||
</div>
|
||||
</f:if>
|
||||
<div class="form-island__loading" aria-hidden="true">
|
||||
<f:render partial="Spinner" arguments="{class: 'form-island__spinner'}" />
|
||||
</div>
|
||||
<style>
|
||||
.form-island { position: relative; }
|
||||
.form-island__loading { position: absolute; inset: 0; z-index: 10; display: flex; align-items: center; justify-content: center; background: rgb(255 255 255 / .7); visibility: hidden; opacity: 0; transition: opacity .15s, visibility .15s; }
|
||||
.form-island.htmx-request .form-island__loading { visibility: visible; opacity: 1; }
|
||||
.form-island__spinner { width: 6rem; height: 6rem; color: rgb(24 82 123); }
|
||||
.sbw .form-island__spinner { color: rgb(233 28 38); }
|
||||
.snz .form-island__spinner { color: rgb(249 195 61); }
|
||||
.suz .form-island__spinner { color: rgb(130 195 198); }
|
||||
.uch .form-island__spinner { color: rgb(25 163 220); }
|
||||
.ser .form-island__spinner { color: rgb(222 44 27); }
|
||||
</style>
|
||||
</div>
|
||||
</f:render>
|
||||
</html>
|
||||
@@ -0,0 +1,112 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en"
|
||||
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
|
||||
|
||||
<f:layout name="Default"/>
|
||||
|
||||
<f:section name="Main">
|
||||
<a id="newsletter-form" class="anchor"></a>
|
||||
<f:render partial="Form/Island" arguments="{id: 'newsletter-island'}" contentAs="content">
|
||||
<div class="container">
|
||||
<f:form method="post" action="subscriptionFormSubmit" name="subscriptionRequest" section="newsletter-form" object="{subscriptionRequest}"
|
||||
hx-boost="true"
|
||||
hx-target="#newsletter-island"
|
||||
hx-select="#newsletter-island"
|
||||
hx-swap="outerHTML"
|
||||
hx-push-url="false"
|
||||
hx-indicator="#newsletter-island">
|
||||
<div class="grid lg:grid-cols-2 lg:gap-x-8 items-start">
|
||||
<div>
|
||||
<f:render section="Field" arguments="{property: 'firstName', label: 'Vorname'}"/>
|
||||
<f:render section="Field" arguments="{property: 'lastName', label: 'Nachname'}"/>
|
||||
<f:render section="Field" arguments="{property: 'email', label: 'E-Mail'}"/>
|
||||
<div class="mb-4">
|
||||
<f:form.validationResults for="subscriptionRequest.consent">
|
||||
<label class="inline-flex items-center">
|
||||
<f:form.checkbox property="consent" value="1" class="form-checkbox{f:if(condition: validationResults.errors.0, then: ' form-checkbox--has-error')}"/>
|
||||
<span class="block ml-2">Ich akzeptiere die <f:link.typolink parameter="{settings.dataProtectionPageUid}" class="underline" target="_blank">Datenschutzbestimmungen</f:link.typolink>*</span>
|
||||
</label>
|
||||
<f:if condition="{validationResults.flattenedErrors}">
|
||||
<div class="text-red-500 mt-2" role="alert">
|
||||
<f:for each="{validationResults.errors}" as="error">
|
||||
{f:translate(key: 'tx_eptheme.message.newsletter.consent.{error.code}', extensionName: 'ep_theme')}
|
||||
<br />
|
||||
</f:for>
|
||||
</div>
|
||||
</f:if>
|
||||
</f:form.validationResults>
|
||||
</div>
|
||||
<div class="hidden lg:block">
|
||||
<button type="submit" class="button bg-button">
|
||||
Anmelden
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<f:form.validationResults for="subscriptionRequest.listIds">
|
||||
<f:for each="{lists}" as="list" iteration="iteration">
|
||||
<f:comment><!-- show different headline for first newsletter in list --></f:comment>
|
||||
<f:if condition="{iteration.isFirst}">
|
||||
<f:then>
|
||||
<h3>
|
||||
News & Angebote per Mail
|
||||
</h3>
|
||||
</f:then>
|
||||
<f:else>
|
||||
<f:comment><!-- show headline only once --></f:comment>
|
||||
<f:if condition="{alertHeadline}">
|
||||
<f:else>
|
||||
<f:variable name="alertHeadline" value="1"/>
|
||||
<h3 class="pt-4">
|
||||
Benachrichtige mich bei Verfügbarkeit
|
||||
</h3>
|
||||
</f:else>
|
||||
</f:if>
|
||||
</f:else>
|
||||
</f:if>
|
||||
<label for="list-{list.id}" class="flex items-center">
|
||||
<f:form.checkbox property="listIds" multiple="1" value="{list.id}" class="form-checkbox"/>
|
||||
<span class="block ml-2">{list.label}</span>
|
||||
</label>
|
||||
</f:for>
|
||||
<f:if condition="{validationResults.flattenedErrors}">
|
||||
<div class="text-red-500 mt-2" role="alert">
|
||||
<f:for each="{validationResults.errors}" as="error">
|
||||
{f:translate(key: 'tx_eptheme.message.newsletter.listIds.{error.code}', extensionName: 'ep_theme')}
|
||||
<br />
|
||||
</f:for>
|
||||
</div>
|
||||
</f:if>
|
||||
</f:form.validationResults>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lg:hidden mt-4">
|
||||
<button type="submit" class="button bg-button">
|
||||
Anmelden
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</f:form>
|
||||
</div>
|
||||
</f:render>
|
||||
</f:section>
|
||||
|
||||
<f:section name="Field">
|
||||
<f:form.validationResults for="subscriptionRequest.{property}">
|
||||
<f:variable name="hasErrors" value="{validationResults.errors.0}"/>
|
||||
<label class="block mb-4">
|
||||
<span class="{f:if(condition: hasErrors, then: 'text-red-500', else: 'text-zinc-700')}">{label}*</span>
|
||||
<f:form.textfield property="{property}" class="form-field {f:if(condition: hasErrors, then: 'form-field--has-error')}"/>
|
||||
<f:if condition="{validationResults.flattenedErrors}">
|
||||
<div class="text-red-500 mt-2" role="alert">
|
||||
<f:for each="{validationResults.errors}" as="error">
|
||||
{f:translate(key: 'tx_eptheme.message.contactForm.{property}.{error.code}', extensionName: 'ep_theme')}
|
||||
<br />
|
||||
</f:for>
|
||||
</div>
|
||||
</f:if>
|
||||
</label>
|
||||
</f:form.validationResults>
|
||||
</f:section>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,41 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en"
|
||||
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
|
||||
|
||||
<f:layout name="Default"/>
|
||||
|
||||
<f:section name="Main">
|
||||
<a id="newsletter-form" class="anchor"></a>
|
||||
<f:render partial="Form/Island" arguments="{id: 'newsletter-island'}" contentAs="content">
|
||||
<div class="container">
|
||||
<f:if condition="{result.success}">
|
||||
<f:then>
|
||||
<div class="bg-ep-primary-light text-white p-4">
|
||||
<h2>
|
||||
Vielen Dank für dein Interesse
|
||||
</h2>
|
||||
<p>
|
||||
Deine Anmeldung muss noch bestätigt werden. Bitte nutze den Link aus der Bestätigungs-E-Mail, die in
|
||||
Kürze bei dir eintreffen sollte.
|
||||
</p>
|
||||
<p class="text-sm">
|
||||
Sieh am besten auch im Spam-Ordner nach.
|
||||
</p>
|
||||
</div>
|
||||
</f:then>
|
||||
<f:else>
|
||||
<div class="bg-red-600 text-white p-4" role="alert">
|
||||
<h2>
|
||||
Das hat leider nicht geklappt
|
||||
</h2>
|
||||
<p>
|
||||
Deine Anmeldung konnte gerade nicht gespeichert werden. Bitte versuche es in ein paar Minuten
|
||||
<f:link.page section="newsletter-form" absolute="1" class="underline">noch einmal</f:link.page>.
|
||||
</p>
|
||||
</div>
|
||||
</f:else>
|
||||
</f:if>
|
||||
</div>
|
||||
</f:render>
|
||||
</f:section>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,43 @@
|
||||
/*! Package version @n8n/[email protected] */
|
||||
:root{--chat--color--primary:#e74266;--chat--color--primary-shade-50:#db4061;--chat--color--primary--shade-100:#cf3c5c;--chat--color--secondary:#20b69e;--chat--color-secondary-shade-50:#1ca08a;--chat--color-white:#fff;--chat--color-light:#f2f4f8;--chat--color-light-shade-50:#e6e9f1;--chat--color-light-shade-100:#c2c5cc;--chat--color-medium:#d2d4d9;--chat--color-dark:#101330;--chat--color-disabled:#d2d4d9;--chat--color-typing:#404040;--chat--spacing:1rem;--chat--border-radius:.25rem;--chat--transition-duration:.15s;--chat--font-family:( -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif );--chat--window--width:400px;--chat--window--height:600px;--chat--window--bottom:var(--chat--spacing);--chat--window--right:var(--chat--spacing);--chat--window--z-index:9999;--chat--window--border:1px solid var(--chat--color-light-shade-50);--chat--window--border-radius:var(--chat--border-radius);--chat--window--margin-bottom:var(--chat--spacing);--chat--header-height:auto;--chat--header--padding:var(--chat--spacing);--chat--header--background:var(--chat--color-dark);--chat--header--color:var(--chat--color-light);--chat--header--border-top:none;--chat--header--border-bottom:none;--chat--header--border-left:none;--chat--header--border-right:none;--chat--heading--font-size:2em;--chat--subtitle--font-size:inherit;--chat--subtitle--line-height:1.8;--chat--message--font-size:1rem;--chat--message--padding:var(--chat--spacing);--chat--message--border-radius:var(--chat--border-radius);--chat--message-line-height:1.5;--chat--message--margin-bottom:calc(var(--chat--spacing)*1);--chat--message--bot--background:var(--chat--color-white);--chat--message--bot--color:var(--chat--color-dark);--chat--message--bot--border:none;--chat--message--user--background:var(--chat--color--secondary);--chat--message--user--color:var(--chat--color-white);--chat--message--user--border:none;--chat--message--pre--background:#0000000d;--chat--messages-list--padding:var(--chat--spacing);--chat--toggle--size:64px;--chat--toggle--width:var(--chat--toggle--size);--chat--toggle--height:var(--chat--toggle--size);--chat--toggle--border-radius:50%;--chat--toggle--background:var(--chat--color--primary);--chat--toggle--hover--background:var(--chat--color--primary-shade-50);--chat--toggle--active--background:var(--chat--color--primary--shade-100);--chat--toggle--color:var(--chat--color-white);--chat--textarea--height:50px;--chat--textarea--max-height:30rem;--chat--input--font-size:inherit;--chat--input--border:0;--chat--input--border-radius:0;--chat--input--padding:.8rem;--chat--input--background:var(--chat--color-white);--chat--input--text-color:initial;--chat--input--line-height:1.5;--chat--input--placeholder--font-size:var(--chat--input--font-size);--chat--input--border-active:0;--chat--input--left--panel--width:2rem;--chat--button--color:var(--chat--color-light);--chat--button--background:var(--chat--color--primary);--chat--button--padding:calc(var(--chat--spacing)*1/2)var(--chat--spacing);--chat--button--border-radius:var(--chat--border-radius);--chat--button--hover--color:var(--chat--color-light);--chat--button--hover--background:var(--chat--color--primary-shade-50);--chat--close--button--color-hover:var(--chat--color--primary);--chat--input--send--button--background:var(--chat--color-white);--chat--input--send--button--color:var(--chat--color--secondary);--chat--input--send--button--background-hover:var(--chat--color--primary-shade-50);--chat--input--send--button--color-hover:var(--chat--color-secondary-shade-50);--chat--input--file--button--background:var(--chat--color-white);--chat--input--file--button--color:var(--chat--color--secondary);--chat--input--file--button--background-hover:var(--chat--input--file--button--background);--chat--input--file--button--color-hover:var(--chat--color-secondary-shade-50);--chat--files-spacing:.25rem;--chat--body--background:var(--chat--color-light);--chat--footer--background:var(--chat--color-light);--chat--footer--color:var(--chat--color-dark)}pre code.hljs{padding:1em;display:block;overflow-x:auto}code.hljs{padding:3px 5px}.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#005cc5}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-comment,.hljs-code,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-wLine truncated
|
||||
/*$vite$:1*/
|
||||
|
||||
:root {
|
||||
/* EP Reisen Brand Colors */
|
||||
--chat--color--primary: #18527b;
|
||||
--chat--color--primary-shade-50: #1a8dc4;
|
||||
--chat--color--primary--shade-100: #177db0;
|
||||
--chat--color--secondary: #be167d;
|
||||
--chat--color-secondary-shade-50: #ab1471;
|
||||
|
||||
/* Layout & Spacing */
|
||||
--chat--border-radius: 12px;
|
||||
--chat--font-size: 0.9rem;
|
||||
--chat--spacing: 1rem;
|
||||
--chat--window--width: 420px;
|
||||
--chat--window--height: 650px;
|
||||
|
||||
/* Header Styling */
|
||||
--chat--header--background: #1d9dd9;
|
||||
--chat--header--color: #ffffff;
|
||||
--chat--heading--font-size: 1.5em;
|
||||
--chat--header--padding: 1.2rem;
|
||||
|
||||
/* Message Bubbles */
|
||||
--chat--message--font-size: 0.95rem;
|
||||
--chat--message--border-radius: 12px;
|
||||
--chat--message--bot--background: #f5f5f5;
|
||||
--chat--message--bot--color: #333333;
|
||||
--chat--message--user--background: #be167d;
|
||||
--chat--message--user--color: #ffffff;
|
||||
|
||||
/* Toggle Button */
|
||||
--chat--toggle--background: #1d9dd9;
|
||||
--chat--toggle--hover--background: #1a8dc4;
|
||||
--chat--toggle--active--background: #177db0;
|
||||
--chat--toggle--color: #ffffff;
|
||||
--chat--toggle--size: 60px;
|
||||
|
||||
/* Input Field */
|
||||
--chat--textarea--height: 55px;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"name":"E&P Skireisen","short_name":"E&P Skireisen","start_url":"/","display":"standalone","gcm_sender_id":"890396972010","gcm_user_visible_only":true}
|
||||
@@ -0,0 +1 @@
|
||||
importScripts('https://static.cleverpush.com/channel/worker/MrDvZ9L2bngnLfnq9.js' + self.location.search);
|
||||