Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
f0b779d724 |
@ -179,7 +179,7 @@ jobs:
|
|||||||
- run:
|
- run:
|
||||||
name: Download additional WP Plugins for tests
|
name: Download additional WP Plugins for tests
|
||||||
command: |
|
command: |
|
||||||
./do download:woo-commerce-zip 7.1.0
|
./do download:woo-commerce-zip 7.0.1
|
||||||
./do download:woo-commerce-subscriptions-zip 4.6.0
|
./do download:woo-commerce-subscriptions-zip 4.6.0
|
||||||
./do download:woo-commerce-memberships-zip 1.23.1
|
./do download:woo-commerce-memberships-zip 1.23.1
|
||||||
./do download:woo-commerce-blocks-zip 8.8.2
|
./do download:woo-commerce-blocks-zip 8.8.2
|
||||||
@ -311,8 +311,7 @@ jobs:
|
|||||||
parallelism: 20
|
parallelism: 20
|
||||||
working_directory: /home/circleci/mailpoet/mailpoet
|
working_directory: /home/circleci/mailpoet/mailpoet
|
||||||
machine:
|
machine:
|
||||||
image: ubuntu-2204:2022.10.2
|
image: ubuntu-2204:2022.07.1
|
||||||
docker_layer_caching: false
|
|
||||||
parameters:
|
parameters:
|
||||||
multisite:
|
multisite:
|
||||||
type: integer
|
type: integer
|
||||||
@ -323,7 +322,7 @@ jobs:
|
|||||||
mysql_command:
|
mysql_command:
|
||||||
type: string
|
type: string
|
||||||
default: ''
|
default: ''
|
||||||
mysql_image:
|
mysql_image_version:
|
||||||
type: string
|
type: string
|
||||||
default: ''
|
default: ''
|
||||||
codeception_image_version:
|
codeception_image_version:
|
||||||
@ -352,7 +351,7 @@ jobs:
|
|||||||
default: 0
|
default: 0
|
||||||
environment:
|
environment:
|
||||||
MYSQL_COMMAND: << parameters.mysql_command >>
|
MYSQL_COMMAND: << parameters.mysql_command >>
|
||||||
MYSQL_IMAGE: << parameters.mysql_image >>
|
MYSQL_IMAGE_VERSION: << parameters.mysql_image_version >>
|
||||||
CODECEPTION_IMAGE_VERSION: << parameters.codeception_image_version >>
|
CODECEPTION_IMAGE_VERSION: << parameters.codeception_image_version >>
|
||||||
WORDPRESS_IMAGE_VERSION: << parameters.wordpress_image_version >>
|
WORDPRESS_IMAGE_VERSION: << parameters.wordpress_image_version >>
|
||||||
steps:
|
steps:
|
||||||
@ -412,12 +411,6 @@ jobs:
|
|||||||
circleci tests glob "tests/acceptance/**/*Cest.php" | circleci tests split --split-by=timings > tests/acceptance/_groups/circleci_split_group
|
circleci tests glob "tests/acceptance/**/*Cest.php" | circleci tests split --split-by=timings > tests/acceptance/_groups/circleci_split_group
|
||||||
fi
|
fi
|
||||||
cat tests/acceptance/_groups/circleci_split_group
|
cat tests/acceptance/_groups/circleci_split_group
|
||||||
- run:
|
|
||||||
name: Create docker containers for test
|
|
||||||
# We experienced some failures when creating containers so we do it explicitly with one retry
|
|
||||||
command: |
|
|
||||||
cd tests/docker
|
|
||||||
docker-compose create || docker-compose create
|
|
||||||
- run:
|
- run:
|
||||||
name: Run acceptance tests
|
name: Run acceptance tests
|
||||||
command: |
|
command: |
|
||||||
@ -483,12 +476,9 @@ jobs:
|
|||||||
integration_tests:
|
integration_tests:
|
||||||
working_directory: /home/circleci/mailpoet/mailpoet
|
working_directory: /home/circleci/mailpoet/mailpoet
|
||||||
machine:
|
machine:
|
||||||
image: ubuntu-2204:2022.10.2
|
image: ubuntu-2204:2022.07.1
|
||||||
docker_layer_caching: false
|
|
||||||
environment:
|
environment:
|
||||||
CODECEPTION_IMAGE_VERSION: << parameters.codeception_image_version >>
|
CODECEPTION_IMAGE_VERSION: << parameters.codeception_image_version >>
|
||||||
MYSQL_COMMAND: << parameters.mysql_command >>
|
|
||||||
MYSQL_IMAGE: << parameters.mysql_image >>
|
|
||||||
parameters:
|
parameters:
|
||||||
codeception_image_version:
|
codeception_image_version:
|
||||||
type: string
|
type: string
|
||||||
@ -511,10 +501,7 @@ jobs:
|
|||||||
multisite:
|
multisite:
|
||||||
type: integer
|
type: integer
|
||||||
default: 0
|
default: 0
|
||||||
mysql_command:
|
woo_core_version:
|
||||||
type: string
|
|
||||||
default: ''
|
|
||||||
mysql_image:
|
|
||||||
type: string
|
type: string
|
||||||
default: ''
|
default: ''
|
||||||
steps:
|
steps:
|
||||||
@ -524,6 +511,14 @@ jobs:
|
|||||||
name: 'Pull test docker images'
|
name: 'Pull test docker images'
|
||||||
# Pull docker images with 3 retries
|
# Pull docker images with 3 retries
|
||||||
command: i='0';while ! docker-compose -f tests/docker/docker-compose.yml pull && ((i < 3)); do sleep 3 && i=$[$i+1]; done
|
command: i='0';while ! docker-compose -f tests/docker/docker-compose.yml pull && ((i < 3)); do sleep 3 && i=$[$i+1]; done
|
||||||
|
- when:
|
||||||
|
condition: << parameters.woo_core_version >>
|
||||||
|
steps:
|
||||||
|
- run:
|
||||||
|
name: Download WooCommerce Core
|
||||||
|
command: |
|
||||||
|
cd tests/docker
|
||||||
|
docker-compose run --rm -w /project --entrypoint "./do download:woo-commerce-zip << parameters.woo_core_version >>" --no-deps codeception_integration
|
||||||
- run:
|
- run:
|
||||||
name: 'PHP Integration tests'
|
name: 'PHP Integration tests'
|
||||||
command: |
|
command: |
|
||||||
@ -634,7 +629,7 @@ workflows:
|
|||||||
- build
|
- build
|
||||||
- acceptance_tests:
|
- acceptance_tests:
|
||||||
<<: *slack-fail-post-step
|
<<: *slack-fail-post-step
|
||||||
name: acceptance_tests_base_and_woo_cot_off
|
name: acceptance_tests
|
||||||
requires:
|
requires:
|
||||||
- unit_tests
|
- unit_tests
|
||||||
- static_analysis_php8
|
- static_analysis_php8
|
||||||
@ -646,6 +641,7 @@ workflows:
|
|||||||
group: woo
|
group: woo
|
||||||
enable_cot: 1
|
enable_cot: 1
|
||||||
enable_cot_sync: 1
|
enable_cot_sync: 1
|
||||||
|
woo_core_version: 7.1.0-rc.2 # Temporarily force COT beta version
|
||||||
requires:
|
requires:
|
||||||
- unit_tests
|
- unit_tests
|
||||||
- static_analysis_php8
|
- static_analysis_php8
|
||||||
@ -657,6 +653,17 @@ workflows:
|
|||||||
group: woo
|
group: woo
|
||||||
enable_cot: 1
|
enable_cot: 1
|
||||||
enable_cot_sync: 0
|
enable_cot_sync: 0
|
||||||
|
woo_core_version: 7.1.0-rc.2 # Temporarily force COT beta version
|
||||||
|
requires:
|
||||||
|
- unit_tests
|
||||||
|
- static_analysis_php8
|
||||||
|
- qa_js
|
||||||
|
- qa_php
|
||||||
|
- acceptance_tests:
|
||||||
|
<<: *slack-fail-post-step
|
||||||
|
name: acceptance_tests_woo_cot_off
|
||||||
|
group: woo
|
||||||
|
woo_core_version: 7.1.0-rc.2 # Temporarily force COT beta version
|
||||||
requires:
|
requires:
|
||||||
- unit_tests
|
- unit_tests
|
||||||
- static_analysis_php8
|
- static_analysis_php8
|
||||||
@ -666,11 +673,21 @@ workflows:
|
|||||||
<<: *slack-fail-post-step
|
<<: *slack-fail-post-step
|
||||||
requires:
|
requires:
|
||||||
- build
|
- build
|
||||||
|
- integration_tests:
|
||||||
|
<<: *slack-fail-post-step
|
||||||
|
group: woo
|
||||||
|
name: integration_test_woocommerce
|
||||||
|
requires:
|
||||||
|
- unit_tests
|
||||||
|
- static_analysis_php8
|
||||||
|
- qa_js
|
||||||
|
- qa_php
|
||||||
- integration_tests:
|
- integration_tests:
|
||||||
<<: *slack-fail-post-step
|
<<: *slack-fail-post-step
|
||||||
group: woo
|
group: woo
|
||||||
enable_cot: 1
|
enable_cot: 1
|
||||||
enable_cot_sync: 1
|
enable_cot_sync: 1
|
||||||
|
woo_core_version: 7.1.0-rc.2 # Temporarily force COT beta version
|
||||||
name: integration_test_woo_cot_sync
|
name: integration_test_woo_cot_sync
|
||||||
requires:
|
requires:
|
||||||
- unit_tests
|
- unit_tests
|
||||||
@ -682,6 +699,7 @@ workflows:
|
|||||||
group: woo
|
group: woo
|
||||||
enable_cot: 1
|
enable_cot: 1
|
||||||
enable_cot_sync: 0
|
enable_cot_sync: 0
|
||||||
|
woo_core_version: 7.1.0-rc.2 # Temporarily force COT beta version
|
||||||
name: integration_test_woo_cot_no_sync
|
name: integration_test_woo_cot_no_sync
|
||||||
requires:
|
requires:
|
||||||
- unit_tests
|
- unit_tests
|
||||||
@ -691,6 +709,7 @@ workflows:
|
|||||||
- integration_tests:
|
- integration_tests:
|
||||||
<<: *slack-fail-post-step
|
<<: *slack-fail-post-step
|
||||||
group: woo
|
group: woo
|
||||||
|
woo_core_version: 7.1.0-rc.2 # Temporarily force COT beta version
|
||||||
name: integration_test_woo_cot_off
|
name: integration_test_woo_cot_off
|
||||||
requires:
|
requires:
|
||||||
- unit_tests
|
- unit_tests
|
||||||
@ -726,13 +745,15 @@ workflows:
|
|||||||
<<: *slack-fail-post-step
|
<<: *slack-fail-post-step
|
||||||
requires:
|
requires:
|
||||||
- build
|
- build
|
||||||
- acceptance_tests_base_and_woo_cot_off
|
- acceptance_tests
|
||||||
- js_tests
|
- js_tests
|
||||||
|
- integration_test_woocommerce
|
||||||
- integration_test_base
|
- integration_test_base
|
||||||
- integration_test_woo_cot_no_sync
|
- integration_test_woo_cot_no_sync
|
||||||
- integration_test_woo_cot_off
|
- integration_test_woo_cot_off
|
||||||
- integration_test_woo_cot_sync
|
- integration_test_woo_cot_sync
|
||||||
- acceptance_tests_woo_cot_sync
|
- acceptance_tests_woo_cot_sync
|
||||||
|
- acceptance_tests_woo_cot_off
|
||||||
- acceptance_tests_woo_cot_no_sync
|
- acceptance_tests_woo_cot_no_sync
|
||||||
|
|
||||||
nightly:
|
nightly:
|
||||||
@ -762,8 +783,8 @@ workflows:
|
|||||||
woo_subscriptions_version: 4.3.0
|
woo_subscriptions_version: 4.3.0
|
||||||
woo_memberships_version: 1.21.0
|
woo_memberships_version: 1.21.0
|
||||||
woo_blocks_version: 6.8.0
|
woo_blocks_version: 6.8.0
|
||||||
mysql_command: --max_allowed_packet=100M --default-storage-engine=MYISAM
|
mysql_command: --max_allowed_packet=100M
|
||||||
mysql_image: mysql:5.5
|
mysql_image_version: 5.7.36
|
||||||
codeception_image_version: 7.4-cli_20220605.0
|
codeception_image_version: 7.4-cli_20220605.0
|
||||||
wordpress_image_version: wp-5.8_php7.3_20221104.1
|
wordpress_image_version: wp-5.8_php7.3_20221104.1
|
||||||
requires:
|
requires:
|
||||||
@ -788,8 +809,6 @@ workflows:
|
|||||||
<<: *slack-fail-post-step
|
<<: *slack-fail-post-step
|
||||||
name: integration_oldest
|
name: integration_oldest
|
||||||
codeception_image_version: 7.2-cli_20220605.0
|
codeception_image_version: 7.2-cli_20220605.0
|
||||||
mysql_command: --max_allowed_packet=100M --default-storage-engine=MYISAM
|
|
||||||
mysql_image: mysql:5.5
|
|
||||||
requires:
|
requires:
|
||||||
- build
|
- build
|
||||||
- build_premium:
|
- build_premium:
|
||||||
|
15
README.md
15
README.md
@ -126,24 +126,23 @@ You can access this help in your command line running `./do` without parameters.
|
|||||||
|
|
||||||
[Read the article.](https://mailpoet.atlassian.net/wiki/spaces/MAILPOET/pages/629374977/Adding+new+templates+to+the+plugin)
|
[Read the article.](https://mailpoet.atlassian.net/wiki/spaces/MAILPOET/pages/629374977/Adding+new+templates+to+the+plugin)
|
||||||
|
|
||||||
## 🚥 Testing with different PHP versions
|
## 🚥 Testing with PHP 7.4 or PHP 8.0
|
||||||
|
|
||||||
To switch the environment to a different PHP version:
|
To switch the environment to PHP 7.4/8.0:
|
||||||
|
|
||||||
1. Check https://github.com/mailpoet/mailpoet/tree/trunk/dev for a list of available PHP versions. Each directory starting with `php` corresponds to a available version.
|
1. Configure the `wordpress` service in `docker-compose.override.yml` to build from the php74 Dockerfile:
|
||||||
2. Configure the `wordpress` service in `docker-compose.override.yml` to build from the desired PHP version Dockerfile (replace {PHP_VERSION} with the name of the directory that corresponds to the version that you want to use):
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
wordpress:
|
wordpress:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: dev/{PHP_VERSION}/Dockerfile
|
dockerfile: dev/php74/Dockerfile # OR dev/php80/Dockerfile
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Run `docker-compose build wordpress`.
|
2. Run `docker-compose build wordpress`.
|
||||||
4. Start the stack with `./do start`.
|
3. Start the stack with `./do start`.
|
||||||
|
|
||||||
To switch back to the default PHP version remove what was added in 2) and, run `docker-compose build wordpress` for application container and `docker-compose build test_wordpress` for tests container,
|
To switch back to PHP 8.1 remove what was added in 1) and, run `docker-compose build wordpress` for application container and `docker-compose build test_wordpress` for tests container,
|
||||||
and start the stack using `./do start`.
|
and start the stack using `./do start`.
|
||||||
|
|
||||||
## ✅ TODO
|
## ✅ TODO
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
FROM php:8.2.0RC6-apache
|
|
||||||
|
|
||||||
ARG UID=1000
|
|
||||||
ARG GID=1000
|
|
||||||
|
|
||||||
# additinal extensions
|
|
||||||
RUN apt-get update \
|
|
||||||
&& apt-get install -y git zlib1g-dev libzip-dev zip wget gnupg msmtp libpng-dev gettext subversion \
|
|
||||||
&& \
|
|
||||||
# Install NodeJS, enable Corepack
|
|
||||||
curl -sL https://deb.nodesource.com/setup_17.x | bash - && \
|
|
||||||
apt-get install -y nodejs build-essential && \
|
|
||||||
corepack enable && \
|
|
||||||
\
|
|
||||||
# Install WP-CLI
|
|
||||||
curl -o /usr/local/bin/wp https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && \
|
|
||||||
chmod +x /usr/local/bin/wp && \
|
|
||||||
\
|
|
||||||
# Clean up
|
|
||||||
apt-get clean && \
|
|
||||||
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
|
||||||
|
|
||||||
COPY dev/php.ini /usr/local/etc/php/conf.d/php_user.ini
|
|
||||||
|
|
||||||
# msmtp config
|
|
||||||
RUN printf "account default\nhost smtp\nport 1025" > /etc/msmtprc
|
|
||||||
|
|
||||||
# xdebug build an config
|
|
||||||
ENV XDEBUGINI_PATH=/usr/local/etc/php/conf.d/xdebug.ini
|
|
||||||
RUN git clone -b "3.2.0RC2" --depth 1 https://github.com/xdebug/xdebug.git /usr/src/php/ext/xdebug \
|
|
||||||
&& docker-php-ext-configure xdebug --enable-xdebug-dev \
|
|
||||||
&& docker-php-ext-install xdebug \
|
|
||||||
&& mkdir /tmp/debug
|
|
||||||
COPY dev/xdebug.ini /tmp/xdebug.ini
|
|
||||||
RUN cat /tmp/xdebug.ini >> $XDEBUGINI_PATH
|
|
||||||
|
|
||||||
# php extensions
|
|
||||||
RUN docker-php-ext-install pdo_mysql
|
|
||||||
RUN docker-php-ext-install mysqli
|
|
||||||
|
|
||||||
# allow .htaccess files (between <Directory /var/www/> and </Directory>, which is WordPress installation)
|
|
||||||
RUN sed -i '/<Directory \/var\/www\/>/,/<\/Directory>/ s/AllowOverride None/AllowOverride All/' /etc/apache2/apache2.conf
|
|
||||||
|
|
||||||
# ensure existing content in /var/www/html respects UID and GID, give Node permissions for Corepack
|
|
||||||
RUN chown -R ${UID}:${GID} /var/www/html && \
|
|
||||||
mkdir -p /.node && chown -R ${UID}:${GID} /.node
|
|
@ -15,7 +15,6 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- my-datavolume:/var/lib/mysql
|
- my-datavolume:/var/lib/mysql
|
||||||
- ./dev/database/create_test_db.sh:/docker-entrypoint-initdb.d/10-create_test_db.sh
|
- ./dev/database/create_test_db.sh:/docker-entrypoint-initdb.d/10-create_test_db.sh
|
||||||
command: --sql_mode=STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,ANSI,ONLY_FULL_GROUP_BY
|
|
||||||
environment:
|
environment:
|
||||||
MYSQL_ROOT_PASSWORD: somewordpress
|
MYSQL_ROOT_PASSWORD: somewordpress
|
||||||
MYSQL_DATABASE: wordpress
|
MYSQL_DATABASE: wordpress
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
<?php
|
||||||
|
|
||||||
// phpcs:disable PSR1.Classes.ClassDeclaration
|
// phpcs:disable PSR1.Classes.ClassDeclaration
|
||||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||||
@ -425,9 +425,6 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
$collection->addCode(function() {
|
$collection->addCode(function() {
|
||||||
return $this->qaCodeSniffer([]);
|
return $this->qaCodeSniffer([]);
|
||||||
});
|
});
|
||||||
$collection->addCode(function() {
|
|
||||||
return $this->qaMinimalPluginStandard([]);
|
|
||||||
});
|
|
||||||
return $collection->run();
|
return $collection->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -539,55 +536,6 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
|
|
||||||
$stringFilesToCheck = !empty($filesToCheck) ? implode(' ', $filesToCheck) : '.';
|
$stringFilesToCheck = !empty($filesToCheck) ? implode(' ', $filesToCheck) : '.';
|
||||||
|
|
||||||
return $this->taskExec($task)
|
|
||||||
->arg('--ignore=' . implode(',', $ignorePatterns))
|
|
||||||
->rawArg($stringFilesToCheck)
|
|
||||||
->run();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function qaMinimalPluginStandard(array $filesToCheck, $opts = ['severity' => 'all']) {
|
|
||||||
$severityFlag = $opts['severity'] === 'all' ? '-w' : '-n';
|
|
||||||
|
|
||||||
$task = implode(' ', [
|
|
||||||
'php -d memory_limit=-1',
|
|
||||||
'./tasks/code_sniffer/vendor/bin/phpcs',
|
|
||||||
'--extensions=php',
|
|
||||||
$severityFlag,
|
|
||||||
'--standard=tasks/code_sniffer/vendor/wporg/plugin-directory/MinimalPluginStandard',
|
|
||||||
'-s',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$ignorePaths = [
|
|
||||||
'.mp_svn',
|
|
||||||
'assets',
|
|
||||||
'doc',
|
|
||||||
'generated',
|
|
||||||
'lib/Config/PopulatorData/Templates',
|
|
||||||
'lib-3rd-party',
|
|
||||||
'node_modules',
|
|
||||||
'plugin_repository',
|
|
||||||
'prefixer/build',
|
|
||||||
'prefixer/vendor',
|
|
||||||
'tasks/code_sniffer/vendor',
|
|
||||||
'tasks/phpstan/vendor',
|
|
||||||
'tasks/makepot',
|
|
||||||
'tools/vendor',
|
|
||||||
'temp',
|
|
||||||
'tests/_data',
|
|
||||||
'tests/_output',
|
|
||||||
'tests/_support/_generated',
|
|
||||||
'vendor',
|
|
||||||
'vendor-prefixed',
|
|
||||||
'views',
|
|
||||||
];
|
|
||||||
|
|
||||||
// the "--ignore" arg takes a list of regexes, we need to anchor and escape them
|
|
||||||
$ignorePatterns = array_map(function (string $path): string {
|
|
||||||
return '^' . preg_quote(__DIR__ . DIRECTORY_SEPARATOR . $path);
|
|
||||||
}, $ignorePaths);
|
|
||||||
|
|
||||||
$stringFilesToCheck = !empty($filesToCheck) ? implode(' ', $filesToCheck) : '.';
|
|
||||||
|
|
||||||
return $this
|
return $this
|
||||||
->taskExec($task)
|
->taskExec($task)
|
||||||
->arg('--ignore=' . implode(',', $ignorePatterns))
|
->arg('--ignore=' . implode(',', $ignorePatterns))
|
||||||
@ -851,9 +799,6 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
->addCode(function () use ($version) {
|
->addCode(function () use ($version) {
|
||||||
$this->releaseCreatePullRequest($version);
|
$this->releaseCreatePullRequest($version);
|
||||||
})
|
})
|
||||||
->addCode(function () use ($version) {
|
|
||||||
$this->releaseRerunCircleWorkflow(\MailPoetTasks\Release\CircleCiController::PROJECT_PREMIUM);
|
|
||||||
})
|
|
||||||
->addCode(function () use ($version) {
|
->addCode(function () use ($version) {
|
||||||
$this->translationsPrepareLanguagePacks($version);
|
$this->translationsPrepareLanguagePacks($version);
|
||||||
})
|
})
|
||||||
@ -1171,18 +1116,6 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
$this->say("Release '$version[name]' info was published on Slack.");
|
$this->say("Release '$version[name]' info was published on Slack.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public function releaseRerunCircleWorkflow(string $project = null) {
|
|
||||||
$circleciController = $this->createCircleCiController();
|
|
||||||
$result = $circleciController->rerunLatestWorkflow($project);
|
|
||||||
// Sometimes can be useful to know which Circle project workflow was restarted
|
|
||||||
$project = $project ? " for the project '{$project}'" : '';
|
|
||||||
if (!$result) {
|
|
||||||
$this->yell("Circle Workflow{$project} was not restarted", 40, 'red');
|
|
||||||
} else {
|
|
||||||
$this->say("Circle Workflow{$project} was started from the beginning");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function downloadWooCommerceBlocksZip($tag = null) {
|
public function downloadWooCommerceBlocksZip($tag = null) {
|
||||||
$this->createWpOrgDownloader('woo-gutenberg-products-block')
|
$this->createWpOrgDownloader('woo-gutenberg-products-block')
|
||||||
->downloadPluginZip('woo-gutenberg-products-block.zip', __DIR__ . '/tests/plugins/', $tag);
|
->downloadPluginZip('woo-gutenberg-products-block.zip', __DIR__ . '/tests/plugins/', $tag);
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -36,8 +36,7 @@
|
|||||||
|
|
||||||
input,
|
input,
|
||||||
select,
|
select,
|
||||||
textarea,
|
textarea {
|
||||||
input[type='text'].components-form-token-field__input {
|
|
||||||
background: right top/26px no-repeat url('../../img/icons/alert.svg');
|
background: right top/26px no-repeat url('../../img/icons/alert.svg');
|
||||||
padding-right: 26px;
|
padding-right: 26px;
|
||||||
}
|
}
|
||||||
|
@ -51,8 +51,4 @@
|
|||||||
.mailpoet_form_field_block {
|
.mailpoet_form_field_block {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mailpoet_form_field_input_nowrap {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -122,21 +122,3 @@ body .components-modal__screen-overlay {
|
|||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
margin-top: $grid-gap-half;
|
margin-top: $grid-gap-half;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mailpoet-locked-badge {
|
|
||||||
align-items: center;
|
|
||||||
background: #fcf9e8;
|
|
||||||
border: .5px solid #f5e6ab;
|
|
||||||
border-radius: 4px;
|
|
||||||
color: #bd8600;
|
|
||||||
display: flex;
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: 500;
|
|
||||||
gap: 4px;
|
|
||||||
height: 20px;
|
|
||||||
letter-spacing: .2px;
|
|
||||||
line-height: 16px;
|
|
||||||
padding: 2px 8px 2px 4px;
|
|
||||||
text-transform: uppercase;
|
|
||||||
width: 82px;
|
|
||||||
}
|
|
||||||
|
@ -22,12 +22,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#mailpoet-wizard-container {
|
|
||||||
.mailpoet-top-bar {
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-wizard-logo {
|
.mailpoet-wizard-logo {
|
||||||
margin-bottom: 100px;
|
margin-bottom: 100px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -41,7 +35,6 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-top: 8px;
|
|
||||||
|
|
||||||
@include respond-to(medium-screen) {
|
@include respond-to(medium-screen) {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -49,7 +42,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mailpoet-wizard-step-illustration {
|
.mailpoet-wizard-step-illustration {
|
||||||
margin-right: $grid-gap-xl;
|
margin-right: $grid-gap;
|
||||||
max-width: $grid-column;
|
max-width: $grid-column;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -70,16 +63,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mailpoet-wizard-step-content {
|
.mailpoet-wizard-step-content {
|
||||||
max-width: 480px;
|
max-width: $grid-column-small + $grid-gap + $grid-column;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
@include respond-to(medium-screen) {
|
@include respond-to(medium-screen) {
|
||||||
max-width: $grid-column;
|
max-width: $grid-column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mailpoet-button {
|
|
||||||
height: 36px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mailpoet-wizard-label {
|
.mailpoet-wizard-label {
|
||||||
@ -122,16 +111,12 @@
|
|||||||
|
|
||||||
.mailpoet-wizard-woocommerce-option {
|
.mailpoet-wizard-woocommerce-option {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
box-shadow: 0 1px 0 0 $color-tertiary-light;
|
box-shadow: 0 -1px 0 0 $color-tertiary-light;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding-bottom: 25px;
|
padding-bottom: 25px;
|
||||||
padding-top: 1px;
|
padding-top: 1px;
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
box-shadow: 0 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mailpoet-wizard-note {
|
.mailpoet-wizard-note {
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
.mailpoet_captcha_form {
|
|
||||||
.mailpoet_icon_button {
|
|
||||||
background: transparent;
|
|
||||||
border: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
img {
|
|
||||||
height: 20px;
|
|
||||||
width: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -112,11 +112,3 @@
|
|||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.authorize-sender-email-and-domain-modal {
|
|
||||||
z-index: 30; // overlay other modals
|
|
||||||
}
|
|
||||||
|
|
||||||
.authorize-sender-email-and-domain-modal-overlay {
|
|
||||||
z-index: $modal-screen-overlay-z-index + 4; // overlay other modals
|
|
||||||
}
|
|
||||||
|
@ -29,6 +29,7 @@ $beamer-dot-size: 8px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mailpoet-top-bar-logo {
|
.mailpoet-top-bar-logo {
|
||||||
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 2px;
|
top: 2px;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
@ -38,10 +39,6 @@ $beamer-dot-size: 8px;
|
|||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a.mailpoet-top-bar-logo {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mailpoet-top-bar-logo-desktop {
|
.mailpoet-top-bar-logo-desktop {
|
||||||
|
@ -19,4 +19,3 @@
|
|||||||
@import 'components-public/public';
|
@import 'components-public/public';
|
||||||
@import 'components-public/animation';
|
@import 'components-public/animation';
|
||||||
@import 'components-public/form_colors';
|
@import 'components-public/form_colors';
|
||||||
@import 'components-public/captcha';
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><rect x="0" fill="none" width="20" height="20"/><g><path d="M2 7h4l5-4v14l-5-4H2V7zm12.69-2.46C14.82 4.59 18 5.92 18 10s-3.18 5.41-3.31 5.46c-.06.03-.13.04-.19.04-.2 0-.39-.12-.46-.31-.11-.26.02-.55.27-.65.11-.05 2.69-1.15 2.69-4.54 0-3.41-2.66-4.53-2.69-4.54-.25-.1-.38-.39-.27-.65.1-.25.39-.38.65-.27zM16 10c0 2.57-2.23 3.43-2.32 3.47-.06.02-.12.03-.18.03-.2 0-.39-.12-.47-.32-.1-.26.04-.55.29-.65.07-.02 1.68-.67 1.68-2.53s-1.61-2.51-1.68-2.53c-.25-.1-.38-.39-.29-.65.1-.25.39-.39.65-.29.09.04 2.32.9 2.32 3.47z"/></g></svg>
|
|
Before Width: | Height: | Size: 587 B |
@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><rect x="0" fill="none" width="20" height="20"/><g><path d="M10.25 1.02c5.1 0 8.75 4.04 8.75 9s-3.65 9-8.75 9c-3.2 0-6.02-1.59-7.68-3.99l2.59-1.52c1.1 1.5 2.86 2.51 4.84 2.51 3.3 0 6-2.79 6-6s-2.7-6-6-6c-1.97 0-3.72 1-4.82 2.49L7 8.02l-6 2v-7L2.89 4.6c1.69-2.17 4.36-3.58 7.36-3.58z"/></g></svg>
|
|
Before Width: | Height: | Size: 355 B |
@ -1,10 +1,12 @@
|
|||||||
import { useState, Fragment } from 'react';
|
import { useState, Fragment } from 'react';
|
||||||
import { DropdownMenu } from '@wordpress/components';
|
import { DropdownMenu } from '@wordpress/components';
|
||||||
|
import { useSelect } from '@wordpress/data';
|
||||||
import { moreVertical, trash } from '@wordpress/icons';
|
import { moreVertical, trash } from '@wordpress/icons';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { Hooks } from 'wp-js-hooks';
|
import { Hooks } from 'wp-js-hooks';
|
||||||
import { PremiumModal } from 'common/premium_modal';
|
import { PremiumModal } from 'common/premium_modal';
|
||||||
import { Step as StepData } from './types';
|
import { Step as StepData } from './types';
|
||||||
|
import { storeName } from '../../store';
|
||||||
import { StepMoreControlsType } from '../../../types/filters';
|
import { StepMoreControlsType } from '../../../types/filters';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -12,6 +14,12 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function StepMoreMenu({ step }: Props): JSX.Element {
|
export function StepMoreMenu({ step }: Props): JSX.Element {
|
||||||
|
const { stepType } = useSelect(
|
||||||
|
(select) => ({
|
||||||
|
stepType: select(storeName).getStepType(step.key),
|
||||||
|
}),
|
||||||
|
[step],
|
||||||
|
);
|
||||||
const [showModal, setShowModal] = useState(false);
|
const [showModal, setShowModal] = useState(false);
|
||||||
|
|
||||||
const moreControls: StepMoreControlsType = Hooks.applyFilters(
|
const moreControls: StepMoreControlsType = Hooks.applyFilters(
|
||||||
@ -45,6 +53,7 @@ export function StepMoreMenu({ step }: Props): JSX.Element {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
step,
|
step,
|
||||||
|
stepType,
|
||||||
);
|
);
|
||||||
|
|
||||||
const slots = Object.values(moreControls).filter(
|
const slots = Object.values(moreControls).filter(
|
||||||
|
@ -21,7 +21,7 @@ const Dropdown: ComponentType<
|
|||||||
}
|
}
|
||||||
> = WpDropdown;
|
> = WpDropdown;
|
||||||
|
|
||||||
function DocumentActions({ children }): JSX.Element {
|
export function DocumentActions({ children }): JSX.Element {
|
||||||
const { automationName, automationStatus, showIconLabels } = useSelect(
|
const { automationName, automationStatus, showIconLabels } = useSelect(
|
||||||
(select) => ({
|
(select) => ({
|
||||||
automationName: select(storeName).getAutomationData().name,
|
automationName: select(storeName).getAutomationData().name,
|
||||||
@ -101,6 +101,3 @@ function DocumentActions({ children }): JSX.Element {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
DocumentActions.displayName = 'DocumentActions';
|
|
||||||
export { DocumentActions };
|
|
||||||
|
@ -9,7 +9,6 @@ import {
|
|||||||
import { useDispatch, useSelect } from '@wordpress/data';
|
import { useDispatch, useSelect } from '@wordpress/data';
|
||||||
import { createContext } from '@wordpress/element';
|
import { createContext } from '@wordpress/element';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { ErrorBoundary } from 'common';
|
|
||||||
import { Chip } from '../chip';
|
import { Chip } from '../chip';
|
||||||
import { ColoredIcon } from '../icons';
|
import { ColoredIcon } from '../icons';
|
||||||
import {
|
import {
|
||||||
@ -71,8 +70,6 @@ function StepError({ stepId }: StepErrorProps): JSX.Element {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
StepError.displayName = 'StepError';
|
|
||||||
|
|
||||||
export function Errors(): JSX.Element | null {
|
export function Errors(): JSX.Element | null {
|
||||||
const [showPopover, setShowPopover] = useState(false);
|
const [showPopover, setShowPopover] = useState(false);
|
||||||
|
|
||||||
@ -163,11 +160,9 @@ export function Errors(): JSX.Element | null {
|
|||||||
__('The following steps are not fully set:', 'mailpoet')
|
__('The following steps are not fully set:', 'mailpoet')
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<ErrorBoundary>
|
{stepErrors.map((error) => (
|
||||||
{stepErrors.map((error) => (
|
<StepError key={error.step_id} stepId={error.step_id} />
|
||||||
<StepError key={error.step_id} stepId={error.step_id} />
|
))}
|
||||||
))}
|
|
||||||
</ErrorBoundary>
|
|
||||||
</Composite>
|
</Composite>
|
||||||
</ErrorsCompositeContext.Provider>
|
</ErrorsCompositeContext.Provider>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
@ -8,7 +8,6 @@ import {
|
|||||||
import { dispatch, useDispatch, useSelect } from '@wordpress/data';
|
import { dispatch, useDispatch, useSelect } from '@wordpress/data';
|
||||||
import { PinnedItems } from '@wordpress/interface';
|
import { PinnedItems } from '@wordpress/interface';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { ErrorBoundary } from 'common';
|
|
||||||
import { DocumentActions } from './document_actions';
|
import { DocumentActions } from './document_actions';
|
||||||
import { Errors } from './errors';
|
import { Errors } from './errors';
|
||||||
import { InserterToggle } from './inserter_toggle';
|
import { InserterToggle } from './inserter_toggle';
|
||||||
@ -228,32 +227,28 @@ export function Header({ showInserterToggle }: Props): JSX.Element {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="edit-site-header_center">
|
<div className="edit-site-header_center">
|
||||||
<ErrorBoundary>
|
<DocumentActions>
|
||||||
<DocumentActions>
|
{() => (
|
||||||
{() => (
|
<div className="mailpoet-automation-editor-dropdown-name-edit">
|
||||||
<div className="mailpoet-automation-editor-dropdown-name-edit">
|
<div className="mailpoet-automation-editor-dropdown-name-edit-title">
|
||||||
<div className="mailpoet-automation-editor-dropdown-name-edit-title">
|
{__('Automation name', 'mailpoet')}
|
||||||
{__('Automation name', 'mailpoet')}
|
|
||||||
</div>
|
|
||||||
<TextControl
|
|
||||||
value={automationName}
|
|
||||||
onChange={(newName) => setAutomationName(newName)}
|
|
||||||
help={__(
|
|
||||||
`Give the automation a name that indicates its purpose. E.g. "Abandoned cart recovery"`,
|
|
||||||
'mailpoet',
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
<TextControl
|
||||||
</DocumentActions>
|
value={automationName}
|
||||||
</ErrorBoundary>
|
onChange={(newName) => setAutomationName(newName)}
|
||||||
|
help={__(
|
||||||
|
`Give the automation a name that indicates its purpose. E.g. "Abandoned cart recovery"`,
|
||||||
|
'mailpoet',
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</DocumentActions>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="edit-site-header_end">
|
<div className="edit-site-header_end">
|
||||||
<div className="edit-site-header__actions">
|
<div className="edit-site-header__actions">
|
||||||
<ErrorBoundary>
|
<Errors />
|
||||||
<Errors />
|
|
||||||
</ErrorBoundary>
|
|
||||||
{automationStatus === AutomationStatus.DRAFT && (
|
{automationStatus === AutomationStatus.DRAFT && (
|
||||||
<>
|
<>
|
||||||
<SaveDraftButton />
|
<SaveDraftButton />
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
export * from './panel';
|
|
||||||
export * from './form-token-field';
|
|
@ -15,7 +15,7 @@ export function DeactivateImmediatelyModal({
|
|||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
className="mailpoet-automatoin-deactivate-modal"
|
className="mailpoet-automatoin-deactivate-modal"
|
||||||
title={__('Stop automation for all subscribers?', 'mailpoet')}
|
title={__('Stop automatoin for all subscribers?', 'mailpoet')}
|
||||||
onRequestClose={onClose}
|
onRequestClose={onClose}
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
import { dispatch } from '@wordpress/data';
|
import { dispatch } from '@wordpress/data';
|
||||||
import { Hooks } from 'wp-js-hooks';
|
|
||||||
import { storeName } from './constants';
|
import { storeName } from './constants';
|
||||||
import { StepType } from './types';
|
import { StepType } from './types';
|
||||||
|
|
||||||
export const registerStepType = (stepType: StepType): void => {
|
export const registerStepType = (stepType: StepType): void => {
|
||||||
dispatch(storeName).registerStepType(
|
dispatch(storeName).registerStepType(stepType);
|
||||||
Hooks.applyFilters('mailpoet.automation.register_step_type', stepType),
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
@ -2,19 +2,11 @@ import { registerStepType } from '../../editor/store';
|
|||||||
import { step as SendEmailStep } from './steps/send_email';
|
import { step as SendEmailStep } from './steps/send_email';
|
||||||
import { step as SomeoneSubscribesTrigger } from './steps/someone-subscribes';
|
import { step as SomeoneSubscribesTrigger } from './steps/someone-subscribes';
|
||||||
import { step as WpUserRegisteredTrigger } from './steps/wp-user-registered';
|
import { step as WpUserRegisteredTrigger } from './steps/wp-user-registered';
|
||||||
import { step as AddTagsAction } from './steps/add_tags';
|
|
||||||
import { step as RemoveTagsAction } from './steps/remove_tags';
|
|
||||||
import { step as AddToListStep } from './steps/add_to_list';
|
|
||||||
import { step as RemoveFromListStep } from './steps/remove_from_list';
|
|
||||||
import { registerStepControls } from './step-controls';
|
import { registerStepControls } from './step-controls';
|
||||||
|
|
||||||
export const initialize = (): void => {
|
export const initialize = (): void => {
|
||||||
registerStepType(SendEmailStep);
|
registerStepType(SendEmailStep);
|
||||||
registerStepType(WpUserRegisteredTrigger);
|
registerStepType(WpUserRegisteredTrigger);
|
||||||
registerStepType(SomeoneSubscribesTrigger);
|
registerStepType(SomeoneSubscribesTrigger);
|
||||||
registerStepType(AddTagsAction);
|
|
||||||
registerStepType(RemoveTagsAction);
|
|
||||||
registerStepType(AddToListStep);
|
|
||||||
registerStepType(RemoveFromListStep);
|
|
||||||
registerStepControls();
|
registerStepControls();
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,7 @@ import { __ } from '@wordpress/i18n';
|
|||||||
import { chartBar } from '@wordpress/icons';
|
import { chartBar } from '@wordpress/icons';
|
||||||
import { Hooks } from 'wp-js-hooks';
|
import { Hooks } from 'wp-js-hooks';
|
||||||
import { MoreControlType, StepMoreControlsType } from '../../../types/filters';
|
import { MoreControlType, StepMoreControlsType } from '../../../types/filters';
|
||||||
|
import { StepType } from '../../../editor/store';
|
||||||
import { Step } from '../../../editor/components/automation/types';
|
import { Step } from '../../../editor/components/automation/types';
|
||||||
|
|
||||||
const emailStatisticsControl = (step: Step): MoreControlType => {
|
const emailStatisticsControl = (step: Step): MoreControlType => {
|
||||||
@ -29,8 +30,12 @@ export function registerStepControls() {
|
|||||||
Hooks.addFilter(
|
Hooks.addFilter(
|
||||||
'mailpoet.automation.step.more-controls',
|
'mailpoet.automation.step.more-controls',
|
||||||
'mailpoet',
|
'mailpoet',
|
||||||
(controls: StepMoreControlsType, step: Step): StepMoreControlsType => {
|
(
|
||||||
if (step.key === 'mailpoet:send-email') {
|
controls: StepMoreControlsType,
|
||||||
|
step: Step,
|
||||||
|
stepType: StepType,
|
||||||
|
): StepMoreControlsType => {
|
||||||
|
if (stepType.key === 'mailpoet:send-email') {
|
||||||
return {
|
return {
|
||||||
statistics: emailStatisticsControl(step),
|
statistics: emailStatisticsControl(step),
|
||||||
...controls,
|
...controls,
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
import { __ } from '@wordpress/i18n';
|
|
||||||
import { tag } from '@wordpress/icons';
|
|
||||||
import { StepType } from '../../../../editor/store';
|
|
||||||
import { LockedBadge } from '../../../../../common/premium_modal/locked_badge';
|
|
||||||
import { PremiumModalForStepEdit } from '../../../../../common/premium_modal';
|
|
||||||
|
|
||||||
export const step: StepType = {
|
|
||||||
key: 'mailpoet:add-tag',
|
|
||||||
group: 'actions',
|
|
||||||
title: __('Add tag', 'mailpoet'),
|
|
||||||
description: __('Add a tag or multiple tags to a subscriber.', 'mailpoet'),
|
|
||||||
subtitle: () => <LockedBadge text={__('Premium', 'mailpoet')} />,
|
|
||||||
foreground: '#00A32A',
|
|
||||||
background: '#EDFAEF',
|
|
||||||
icon: () => (
|
|
||||||
<div style={{ width: '100%', height: '100%', scale: '1.4' }}>{tag}</div>
|
|
||||||
),
|
|
||||||
edit: () => (
|
|
||||||
<PremiumModalForStepEdit
|
|
||||||
tracking={{
|
|
||||||
utm_medium: 'upsell_modal',
|
|
||||||
utm_campaign: 'create_automation_editor_add_tag',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{__('Adding tags is a premium feature.', 'mailpoet')}
|
|
||||||
</PremiumModalForStepEdit>
|
|
||||||
),
|
|
||||||
} as const;
|
|
@ -1,28 +0,0 @@
|
|||||||
import { __ } from '@wordpress/i18n';
|
|
||||||
import { list } from '@wordpress/icons';
|
|
||||||
import { StepType } from '../../../../editor/store/types';
|
|
||||||
import { PremiumModalForStepEdit } from '../../../../../common/premium_modal';
|
|
||||||
import { LockedBadge } from '../../../../../common/premium_modal/locked_badge';
|
|
||||||
|
|
||||||
export const step: StepType = {
|
|
||||||
key: 'mailpoet:add-to-list',
|
|
||||||
group: 'actions',
|
|
||||||
title: __('Add to list', 'mailpoet'),
|
|
||||||
description: __('Add a subscriber to a list.', 'mailpoet'),
|
|
||||||
subtitle: () => <LockedBadge text={__('Premium', 'mailpoet')} />,
|
|
||||||
foreground: '#00A32A',
|
|
||||||
background: '#EDFAEF',
|
|
||||||
icon: () => (
|
|
||||||
<div style={{ width: '100%', height: '100%', scale: '1.12' }}>{list}</div>
|
|
||||||
),
|
|
||||||
edit: () => (
|
|
||||||
<PremiumModalForStepEdit
|
|
||||||
tracking={{
|
|
||||||
utm_medium: 'upsell_modal',
|
|
||||||
utm_campaign: 'create_automation_editor_add_to_list',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{__('Adding subscribers to lists is a premium feature.', 'mailpoet')}
|
|
||||||
</PremiumModalForStepEdit>
|
|
||||||
),
|
|
||||||
} as const;
|
|
@ -1,28 +0,0 @@
|
|||||||
import { __ } from '@wordpress/i18n';
|
|
||||||
import { list } from '@wordpress/icons';
|
|
||||||
import { StepType } from '../../../../editor/store/types';
|
|
||||||
import { PremiumModalForStepEdit } from '../../../../../common/premium_modal';
|
|
||||||
import { LockedBadge } from '../../../../../common/premium_modal/locked_badge';
|
|
||||||
|
|
||||||
export const step: StepType = {
|
|
||||||
key: 'mailpoet:remove-from-list',
|
|
||||||
group: 'actions',
|
|
||||||
title: __('Remove from list', 'mailpoet'),
|
|
||||||
description: __('Remove a subscriber from a list.', 'mailpoet'),
|
|
||||||
subtitle: () => <LockedBadge text={__('Premium', 'mailpoet')} />,
|
|
||||||
foreground: '#00A32A',
|
|
||||||
background: '#EDFAEF',
|
|
||||||
icon: () => (
|
|
||||||
<div style={{ width: '100%', height: '100%', scale: '1.12' }}>{list}</div>
|
|
||||||
),
|
|
||||||
edit: () => (
|
|
||||||
<PremiumModalForStepEdit
|
|
||||||
tracking={{
|
|
||||||
utm_medium: 'upsell_modal',
|
|
||||||
utm_campaign: 'create_automation_editor_remove_from_list',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{__('Removing subscribers from lists is a premium feature.', 'mailpoet')}
|
|
||||||
</PremiumModalForStepEdit>
|
|
||||||
),
|
|
||||||
} as const;
|
|
@ -1,31 +0,0 @@
|
|||||||
import { __ } from '@wordpress/i18n';
|
|
||||||
import { tag } from '@wordpress/icons';
|
|
||||||
import { StepType } from '../../../../editor/store';
|
|
||||||
import { LockedBadge } from '../../../../../common/premium_modal/locked_badge';
|
|
||||||
import { PremiumModalForStepEdit } from '../../../../../common/premium_modal';
|
|
||||||
|
|
||||||
export const step: StepType = {
|
|
||||||
key: 'mailpoet:remove-tag',
|
|
||||||
group: 'actions',
|
|
||||||
title: __('Remove tag', 'mailpoet'),
|
|
||||||
description: __(
|
|
||||||
'Remove a tag or multiple tags from a subscriber',
|
|
||||||
'mailpoet',
|
|
||||||
),
|
|
||||||
subtitle: () => <LockedBadge text={__('Premium', 'mailpoet')} />,
|
|
||||||
foreground: '#00A32A',
|
|
||||||
background: '#EDFAEF',
|
|
||||||
icon: () => (
|
|
||||||
<div style={{ width: '100%', height: '100%', scale: '1.4' }}>{tag}</div>
|
|
||||||
),
|
|
||||||
edit: () => (
|
|
||||||
<PremiumModalForStepEdit
|
|
||||||
tracking={{
|
|
||||||
utm_medium: 'upsell_modal',
|
|
||||||
utm_campaign: 'create_automation_editor_remove_tag',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{__('Removing tags is a premium feature.', 'mailpoet')}
|
|
||||||
</PremiumModalForStepEdit>
|
|
||||||
),
|
|
||||||
} as const;
|
|
@ -3,10 +3,8 @@ import { dispatch, useSelect } from '@wordpress/data';
|
|||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { storeName } from '../../../../../editor/store';
|
import { storeName } from '../../../../../editor/store';
|
||||||
import { segments } from './segment';
|
import { segments } from './segment';
|
||||||
import {
|
import { PlainBodyTitle } from '../../../../../editor/components/panel';
|
||||||
PlainBodyTitle,
|
import { FormTokenField } from '../../../components/form-token-field';
|
||||||
FormTokenField,
|
|
||||||
} from '../../../../../editor/components';
|
|
||||||
|
|
||||||
export function ListPanel(): JSX.Element {
|
export function ListPanel(): JSX.Element {
|
||||||
const { selectedStep } = useSelect(
|
const { selectedStep } = useSelect(
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { FormTokenItem } from '../../../../../editor/components';
|
import { FormTokenItem } from '../../../components/form-token-field';
|
||||||
|
|
||||||
type Segment = FormTokenItem & {
|
type Segment = FormTokenItem & {
|
||||||
type: string;
|
type: string;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { FormTokenItem } from '../../../../../editor/components';
|
import { FormTokenItem } from '../../../components/form-token-field';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
|
@ -3,11 +3,9 @@ import { dispatch, useSelect } from '@wordpress/data';
|
|||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import ReactStringReplace from 'react-string-replace';
|
import ReactStringReplace from 'react-string-replace';
|
||||||
import { storeName } from '../../../../../editor/store';
|
import { storeName } from '../../../../../editor/store';
|
||||||
import {
|
import { PlainBodyTitle } from '../../../../../editor/components/panel';
|
||||||
PlainBodyTitle,
|
|
||||||
FormTokenField,
|
|
||||||
} from '../../../../../editor/components';
|
|
||||||
import { userRoles } from './role';
|
import { userRoles } from './role';
|
||||||
|
import { FormTokenField } from '../../../components/form-token-field';
|
||||||
|
|
||||||
function SettingsInfoText(): JSX.Element {
|
function SettingsInfoText(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
@ -92,7 +92,6 @@ function AuthorizeSenderEmailAndDomainModal({
|
|||||||
<Modal
|
<Modal
|
||||||
onRequestClose={onRequestClose}
|
onRequestClose={onRequestClose}
|
||||||
contentClassName="authorize-sender-email-and-domain-modal"
|
contentClassName="authorize-sender-email-and-domain-modal"
|
||||||
overlayClassName="authorize-sender-email-and-domain-modal-overlay"
|
|
||||||
>
|
>
|
||||||
<Tabs activeKey={initialTab}>
|
<Tabs activeKey={initialTab}>
|
||||||
<Tab
|
<Tab
|
||||||
|
@ -6,7 +6,7 @@ type Props = {
|
|||||||
active: string;
|
active: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
function Categories({ onSelect, categories, active }: Props) {
|
export function Categories({ onSelect, categories, active }: Props) {
|
||||||
const cats = categories.map((category) => (
|
const cats = categories.map((category) => (
|
||||||
<CategoriesItem
|
<CategoriesItem
|
||||||
{...category}
|
{...category}
|
||||||
@ -18,6 +18,3 @@ function Categories({ onSelect, categories, active }: Props) {
|
|||||||
|
|
||||||
return <div className="mailpoet-categories">{cats}</div>;
|
return <div className="mailpoet-categories">{cats}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
Categories.displayName = 'Categories';
|
|
||||||
export { Categories };
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import ReactDatePicker, { ReactDatePickerProps } from 'react-datepicker';
|
import ReactDatePicker, { ReactDatePickerProps } from 'react-datepicker';
|
||||||
import { MailPoet } from 'mailpoet';
|
import { MailPoet } from 'mailpoet';
|
||||||
import { withBoundary } from '../error_boundary';
|
|
||||||
|
|
||||||
type Props = ReactDatePickerProps & {
|
type Props = ReactDatePickerProps & {
|
||||||
dimension?: 'small';
|
dimension?: 'small';
|
||||||
@ -10,7 +9,7 @@ type Props = ReactDatePickerProps & {
|
|||||||
iconEnd?: JSX.Element;
|
iconEnd?: JSX.Element;
|
||||||
};
|
};
|
||||||
|
|
||||||
function Datepicker({
|
export function Datepicker({
|
||||||
dimension,
|
dimension,
|
||||||
isFullWidth,
|
isFullWidth,
|
||||||
iconStart,
|
iconStart,
|
||||||
@ -35,8 +34,3 @@ function Datepicker({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datepicker.displayName = 'Datepicker';
|
|
||||||
const DatepickerWithBoundary = withBoundary(Datepicker);
|
|
||||||
|
|
||||||
export { DatepickerWithBoundary as Datepicker };
|
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
import { Children, Component } from '@wordpress/element';
|
|
||||||
import { ComponentType } from 'react';
|
|
||||||
import { getComponentDisplayName } from './utils';
|
|
||||||
|
|
||||||
type ErrorBoundaryState = {
|
|
||||||
hasError: boolean;
|
|
||||||
error?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ErrorBoundaryProps = {
|
|
||||||
onError?: (Error_Boundary_State) => ComponentType;
|
|
||||||
};
|
|
||||||
|
|
||||||
export class ErrorBoundary extends Component<
|
|
||||||
ErrorBoundaryProps,
|
|
||||||
ErrorBoundaryState
|
|
||||||
> {
|
|
||||||
constructor(props: ErrorBoundaryProps) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
hasError: false,
|
|
||||||
error: '',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static getDerivedStateFromError(error: Error & { fileName?: string }) {
|
|
||||||
return {
|
|
||||||
hasError: true,
|
|
||||||
error: `${error?.toString()} \nFile name: ${
|
|
||||||
error?.fileName ?? 'No fileName reported'
|
|
||||||
} \nStack trace: ${error?.stack ?? 'No stack trace reported'}`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidCatch(error, errorInfo) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log('logging', { error, errorInfo });
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { onError } = this.props;
|
|
||||||
const { hasError, error } = this.state;
|
|
||||||
if (hasError) {
|
|
||||||
if (onError) {
|
|
||||||
return onError(this.state);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<h1>
|
|
||||||
The application{' '}
|
|
||||||
<strong>
|
|
||||||
{Children.map(this.props.children, (child) =>
|
|
||||||
getComponentDisplayName(child as ComponentType),
|
|
||||||
).join(', ')}{' '}
|
|
||||||
</strong>
|
|
||||||
encountered an error
|
|
||||||
</h1>
|
|
||||||
<p>
|
|
||||||
Please report the following error to{' '}
|
|
||||||
<a href="https://www.mailpoet.com/support/">MailPoet support</a>
|
|
||||||
</p>
|
|
||||||
<pre>{error}</pre>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return this.props.children;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
export * from './utils';
|
|
||||||
export * from './error_boundary';
|
|
||||||
export * from './with_boundary';
|
|
@ -1,4 +0,0 @@
|
|||||||
import { ComponentType } from 'react';
|
|
||||||
|
|
||||||
export const getComponentDisplayName = (component: ComponentType): string =>
|
|
||||||
component.displayName || component.name || 'Unknown application/component';
|
|
@ -1,14 +0,0 @@
|
|||||||
import { ComponentType, JSXElementConstructor } from 'react';
|
|
||||||
import { ErrorBoundary, ErrorBoundaryProps } from './error_boundary';
|
|
||||||
|
|
||||||
export const withBoundary = <P extends Record<string, unknown> | unknown>(
|
|
||||||
Bound: JSXElementConstructor<P>,
|
|
||||||
props?: ErrorBoundaryProps,
|
|
||||||
): ComponentType<P> =>
|
|
||||||
function bounder(boundProps: P) {
|
|
||||||
return (
|
|
||||||
<ErrorBoundary {...props}>
|
|
||||||
<Bound {...boundProps} />
|
|
||||||
</ErrorBoundary>
|
|
||||||
);
|
|
||||||
};
|
|
@ -7,7 +7,7 @@ type Props = InputHTMLAttributes<HTMLInputElement> & {
|
|||||||
automationId?: string;
|
automationId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
function Toggle({
|
export function Toggle({
|
||||||
dimension,
|
dimension,
|
||||||
onCheck,
|
onCheck,
|
||||||
automationId,
|
automationId,
|
||||||
@ -33,7 +33,3 @@ function Toggle({
|
|||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Toggle.displayName = 'FormToggle';
|
|
||||||
|
|
||||||
export { Toggle };
|
|
||||||
|
@ -7,4 +7,3 @@ export * from './loading';
|
|||||||
export * from './form';
|
export * from './form';
|
||||||
export * from './tag';
|
export * from './tag';
|
||||||
export * from './listings';
|
export * from './listings';
|
||||||
export * from './error_boundary';
|
|
||||||
|
@ -63,7 +63,7 @@ type NewsletterStatusProps = {
|
|||||||
status?: string;
|
status?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
function NewsletterStatus({
|
export function NewsletterStatus({
|
||||||
scheduledFor,
|
scheduledFor,
|
||||||
processed,
|
processed,
|
||||||
total,
|
total,
|
||||||
@ -150,6 +150,3 @@ function NewsletterStatus({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
NewsletterStatus.displayName = 'NewsletterStatus';
|
|
||||||
export { NewsletterStatus };
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useSelect } from '@wordpress/data';
|
import { useSelect } from '@wordpress/data';
|
||||||
import { MailPoet } from 'mailpoet';
|
import { MailPoet } from 'mailpoet';
|
||||||
import { withBoundary } from '../error_boundary';
|
|
||||||
|
|
||||||
function UnsavedChangesNotice({ storeName }) {
|
export function UnsavedChangesNotice({ storeName }) {
|
||||||
const hasUnsavedChanges = useSelect(
|
const hasUnsavedChanges = useSelect(
|
||||||
(sel) => sel(storeName).hasUnsavedChanges(),
|
(sel) => sel(storeName).hasUnsavedChanges(),
|
||||||
[],
|
[],
|
||||||
@ -25,7 +24,3 @@ function UnsavedChangesNotice({ storeName }) {
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
UnsavedChangesNotice.displayName = 'UnsavedChangesNotice';
|
|
||||||
const UnsavedChangesNoticeWithBoundary = withBoundary(UnsavedChangesNotice);
|
|
||||||
export { UnsavedChangesNoticeWithBoundary as UnsavedChangesNotice };
|
|
||||||
|
@ -13,7 +13,6 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
Modal,
|
Modal,
|
||||||
} from '@wordpress/components';
|
} from '@wordpress/components';
|
||||||
import { dispatch } from '@wordpress/data';
|
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { MailPoet } from 'mailpoet';
|
import { MailPoet } from 'mailpoet';
|
||||||
import {
|
import {
|
||||||
@ -22,8 +21,6 @@ import {
|
|||||||
useUpgradeInfo,
|
useUpgradeInfo,
|
||||||
UtmParams,
|
UtmParams,
|
||||||
} from './upgrade_info';
|
} from './upgrade_info';
|
||||||
import { storeName } from '../../automation/editor/store';
|
|
||||||
import { withBoundary } from '../error_boundary';
|
|
||||||
|
|
||||||
export const premiumValidAndActive =
|
export const premiumValidAndActive =
|
||||||
premiumFeaturesEnabled && MailPoet.premiumActive;
|
premiumFeaturesEnabled && MailPoet.premiumActive;
|
||||||
@ -52,7 +49,11 @@ const getCta = (state: State, upgradeInfo: UpgradeInfo): string => {
|
|||||||
return cta;
|
return cta;
|
||||||
};
|
};
|
||||||
|
|
||||||
function PremiumModal({ children, tracking, ...props }: Props): JSX.Element {
|
export function PremiumModal({
|
||||||
|
children,
|
||||||
|
tracking,
|
||||||
|
...props
|
||||||
|
}: Props): JSX.Element {
|
||||||
const [state, setState] = useState<State>();
|
const [state, setState] = useState<State>();
|
||||||
const upgradeInfo = useUpgradeInfo(tracking);
|
const upgradeInfo = useUpgradeInfo(tracking);
|
||||||
|
|
||||||
@ -125,44 +126,3 @@ function PremiumModal({ children, tracking, ...props }: Props): JSX.Element {
|
|||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
PremiumModal.displayName = 'PremiumModal';
|
|
||||||
|
|
||||||
type EditProps = Omit<Props, 'onRequestClose'>;
|
|
||||||
|
|
||||||
function PremiumModalForStepEdit({
|
|
||||||
children,
|
|
||||||
...props
|
|
||||||
}: EditProps): JSX.Element {
|
|
||||||
const [showModal, setShowModal] = useState(true);
|
|
||||||
useEffect(() => {
|
|
||||||
if (showModal) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { selectStep } = dispatch(storeName);
|
|
||||||
selectStep(undefined);
|
|
||||||
setShowModal(true);
|
|
||||||
}, [showModal]);
|
|
||||||
if (!showModal) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<PremiumModal
|
|
||||||
onRequestClose={() => {
|
|
||||||
setShowModal(false);
|
|
||||||
}}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</PremiumModal>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
PremiumModalForStepEdit.displayName = 'PremiumModalForStepEdit';
|
|
||||||
const PremiumModalForStepEditWithBoundary = withBoundary(
|
|
||||||
PremiumModalForStepEdit,
|
|
||||||
);
|
|
||||||
export {
|
|
||||||
PremiumModal,
|
|
||||||
PremiumModalForStepEditWithBoundary as PremiumModalForStepEdit,
|
|
||||||
};
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
const lockIcon = (
|
|
||||||
<svg
|
|
||||||
width="12"
|
|
||||||
height="12"
|
|
||||||
viewBox="0 0 12 12"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<g clipPath="url(#clip0_1896_34966)">
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M6 1.625C4.96447 1.625 4.125 2.46447 4.125 3.5V5H3.5C3.22386 5 3 5.22386 3 5.5V9.5C3 9.77614 3.22386 10 3.5 10H8.5C8.77614 10 9 9.77614 9 9.5V5.5C9 5.22386 8.77614 5 8.5 5H7.875V3.5C7.875 2.46447 7.03553 1.625 6 1.625ZM7.125 5V3.5C7.125 2.87868 6.62132 2.375 6 2.375C5.37868 2.375 4.875 2.87868 4.875 3.5V5H7.125Z"
|
|
||||||
fill="#BD8600"
|
|
||||||
/>
|
|
||||||
</g>
|
|
||||||
<defs>
|
|
||||||
<clipPath id="clip0_1896_34966">
|
|
||||||
<rect width="12" height="12" fill="white" />
|
|
||||||
</clipPath>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
|
|
||||||
export function LockedBadge({ text }): JSX.Element {
|
|
||||||
return (
|
|
||||||
<span className="mailpoet-locked-badge">
|
|
||||||
{lockIcon} {text}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
@ -77,5 +77,5 @@ Preview.defaultProps = {
|
|||||||
onDisplayTypeChange: () => {},
|
onDisplayTypeChange: () => {},
|
||||||
selectedDisplayType: 'desktop',
|
selectedDisplayType: 'desktop',
|
||||||
};
|
};
|
||||||
Preview.displayName = 'FormEditorPreview';
|
|
||||||
export { Preview };
|
export { Preview };
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import { withBoundary } from './error_boundary';
|
|
||||||
|
|
||||||
function ScrollToTopComponent({ children, location: { pathname } }) {
|
function ScrollToTopComponent({ children, location: { pathname } }) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -10,5 +9,4 @@ function ScrollToTopComponent({ children, location: { pathname } }) {
|
|||||||
return children || null;
|
return children || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrollToTopComponent.displayName = 'ScrollToTopComponent';
|
export const ScrollToTop = withRouter(ScrollToTopComponent);
|
||||||
export const ScrollToTop = withRouter(withBoundary(ScrollToTopComponent));
|
|
||||||
|
@ -163,5 +163,5 @@ SenderEmailAddressWarning.defaultProps = {
|
|||||||
showSenderDomainWarning: false,
|
showSenderDomainWarning: false,
|
||||||
onSuccessfulEmailOrDomainAuthorization: noop,
|
onSuccessfulEmailOrDomainAuthorization: noop,
|
||||||
};
|
};
|
||||||
SenderEmailAddressWarning.displayName = 'SenderEmailAddressWarning';
|
|
||||||
export { SenderEmailAddressWarning };
|
export { SenderEmailAddressWarning };
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import range from 'lodash/range';
|
import range from 'lodash/range';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { withBoundary } from 'common';
|
|
||||||
import { ContentWrapperFix } from './content_wrapper_fix';
|
import { ContentWrapperFix } from './content_wrapper_fix';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -9,7 +8,7 @@ type Props = {
|
|||||||
titles?: string[];
|
titles?: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
function StepsComponent({ count, current, titles }: Props) {
|
function Steps({ count, current, titles }: Props) {
|
||||||
return (
|
return (
|
||||||
<div className="mailpoet-steps">
|
<div className="mailpoet-steps">
|
||||||
<ContentWrapperFix />
|
<ContentWrapperFix />
|
||||||
@ -36,9 +35,8 @@ function StepsComponent({ count, current, titles }: Props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
StepsComponent.defaultProps = {
|
Steps.defaultProps = {
|
||||||
titles: [],
|
titles: [],
|
||||||
};
|
};
|
||||||
StepsComponent.displayName = 'StepsComponent';
|
|
||||||
const Steps = withBoundary(StepsComponent);
|
|
||||||
export { Steps };
|
export { Steps };
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
import { noop } from 'lodash';
|
import { noop } from 'lodash';
|
||||||
|
|
||||||
import { Props as TabProps, Tabs } from './tabs';
|
import { Tabs, Props as TabProps } from './tabs';
|
||||||
|
|
||||||
function RouterAwareTabs(
|
function RouterAwareTabs(
|
||||||
props: TabProps & {
|
props: TabProps & {
|
||||||
@ -105,6 +105,4 @@ function RoutedTabs({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
RoutedTabs.displayName = 'RoutedTabs';
|
|
||||||
|
|
||||||
export { RoutedTabs };
|
export { RoutedTabs };
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Heading } from 'common/typography/heading/heading';
|
import { Heading } from 'common/typography/heading/heading';
|
||||||
import { SegmentTags, StringTags } from '../tags';
|
import { Tags } from '../tags';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Tags',
|
title: 'Tags',
|
||||||
@ -18,20 +18,15 @@ export function Segments() {
|
|||||||
<>
|
<>
|
||||||
<Heading level={1}>Tags</Heading>
|
<Heading level={1}>Tags</Heading>
|
||||||
<Heading level={2}>Segments</Heading>
|
<Heading level={2}>Segments</Heading>
|
||||||
<SegmentTags segments={segments} dimension="large" />
|
<Tags segments={segments} dimension="large" />
|
||||||
<div className="mailpoet-gap" />
|
<div className="mailpoet-gap" />
|
||||||
<SegmentTags segments={segments}>
|
<Tags segments={segments}>
|
||||||
<span>Prefix: </span>
|
<span>Prefix: </span>
|
||||||
</SegmentTags>
|
</Tags>
|
||||||
<Heading level={2}>Strings</Heading>
|
<Heading level={2}>Strings</Heading>
|
||||||
<StringTags strings={strings} dimension="large" variant="good" />
|
<Tags strings={strings} dimension="large" variant="good" />
|
||||||
<div className="mailpoet-gap" />
|
<div className="mailpoet-gap" />
|
||||||
<StringTags
|
<Tags strings={strings} dimension="large" variant="good" isInverted />
|
||||||
strings={strings}
|
|
||||||
dimension="large"
|
|
||||||
variant="good"
|
|
||||||
isInverted
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -3,36 +3,11 @@ import { Tag, TagVariant } from './tag';
|
|||||||
import { Tooltip } from '../tooltip/tooltip';
|
import { Tooltip } from '../tooltip/tooltip';
|
||||||
import { MailPoet } from '../../mailpoet';
|
import { MailPoet } from '../../mailpoet';
|
||||||
|
|
||||||
type SharedTagProps = {
|
|
||||||
children?: ReactNode;
|
|
||||||
dimension?: 'large';
|
|
||||||
variant?: TagVariant;
|
|
||||||
isInverted?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
type TagData = {
|
|
||||||
name: string;
|
|
||||||
target?: string;
|
|
||||||
tooltip?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type TagProps = SharedTagProps & {
|
|
||||||
tags: TagData[];
|
|
||||||
};
|
|
||||||
|
|
||||||
type StringTagsProps = SharedTagProps & {
|
|
||||||
strings: string[];
|
|
||||||
};
|
|
||||||
|
|
||||||
type Segment = {
|
type Segment = {
|
||||||
name: string;
|
name: string;
|
||||||
id?: string;
|
id?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type SegmentTagsProps = SharedTagProps & {
|
|
||||||
segments: Segment[];
|
|
||||||
};
|
|
||||||
|
|
||||||
type SubscriberTag = {
|
type SubscriberTag = {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
@ -40,96 +15,99 @@ type SubscriberTag = {
|
|||||||
tag_id: string;
|
tag_id: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type SubscriberTagsProps = SharedTagProps & {
|
type Props = {
|
||||||
subscribers: SubscriberTag[];
|
children?: ReactNode;
|
||||||
|
dimension?: 'large';
|
||||||
|
segments?: Segment[];
|
||||||
|
subscriberTags?: SubscriberTag[];
|
||||||
|
strings?: string[];
|
||||||
|
variant?: TagVariant;
|
||||||
|
isInverted?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
function Tags({ children, tags, dimension, variant, isInverted }: TagProps) {
|
function Tags({
|
||||||
|
children,
|
||||||
|
dimension,
|
||||||
|
segments,
|
||||||
|
subscriberTags,
|
||||||
|
strings,
|
||||||
|
variant,
|
||||||
|
isInverted,
|
||||||
|
}: Props) {
|
||||||
return (
|
return (
|
||||||
<div className="mailpoet-tags">
|
<div className="mailpoet-tags">
|
||||||
{children}
|
{children}
|
||||||
{tags.map((item) => {
|
{segments &&
|
||||||
const tag = (
|
segments.map((segment) => {
|
||||||
<Tag
|
const tag = (
|
||||||
key={item.name}
|
<Tag key={segment.name} dimension={dimension} variant="list">
|
||||||
dimension={dimension}
|
{segment.name}
|
||||||
variant={variant || 'list'}
|
</Tag>
|
||||||
isInverted={isInverted}
|
);
|
||||||
>
|
if (!segment.id) {
|
||||||
{item.name}
|
return tag;
|
||||||
</Tag>
|
}
|
||||||
);
|
const randomId = Math.random().toString(36).substring(2, 15);
|
||||||
if (!item.target) {
|
const tooltipId = `segment-tooltip-${randomId}`;
|
||||||
return tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
const randomId = Math.random().toString(36).substring(2, 15);
|
return (
|
||||||
const tooltipId = `segment-tooltip-${randomId}`;
|
<div key={randomId}>
|
||||||
return (
|
|
||||||
<div key={randomId}>
|
|
||||||
{item.tooltip && (
|
|
||||||
<Tooltip id={tooltipId} place="top">
|
<Tooltip id={tooltipId} place="top">
|
||||||
{MailPoet.I18n.t('viewFilteredSubscribersMessage')}
|
{MailPoet.I18n.t('viewFilteredSubscribersMessage')}
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
<a
|
||||||
<a data-tip="" data-for={tooltipId} href={item.target}>
|
data-tip=""
|
||||||
{tag}
|
data-for={tooltipId}
|
||||||
</a>
|
href={`admin.php?page=mailpoet-subscribers#/filter[segment=${segment.id}]`}
|
||||||
</div>
|
>
|
||||||
);
|
{tag}
|
||||||
})}
|
</a>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{subscriberTags &&
|
||||||
|
subscriberTags.map((subscriberTag) => {
|
||||||
|
const randomId = Math.random().toString(36).substring(2, 15);
|
||||||
|
const tooltipId = `tag-tooltip-${randomId}`;
|
||||||
|
const tag = (
|
||||||
|
<Tag
|
||||||
|
key={subscriberTag.name}
|
||||||
|
dimension={dimension}
|
||||||
|
variant={variant || 'list'}
|
||||||
|
isInverted={isInverted}
|
||||||
|
>
|
||||||
|
{subscriberTag.name}
|
||||||
|
</Tag>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={randomId}>
|
||||||
|
<Tooltip id={tooltipId} place="top">
|
||||||
|
{MailPoet.I18n.t('viewFilteredSubscribersMessage')}
|
||||||
|
</Tooltip>
|
||||||
|
<a
|
||||||
|
data-tip=""
|
||||||
|
data-for={tooltipId}
|
||||||
|
href={`admin.php?page=mailpoet-subscribers#/filter[tag=${subscriberTag.tag_id}]`}
|
||||||
|
>
|
||||||
|
{tag}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{strings &&
|
||||||
|
strings.map((string) => (
|
||||||
|
<Tag
|
||||||
|
key={string}
|
||||||
|
dimension={dimension}
|
||||||
|
variant={variant || 'list'} // due to backward compatibility we use `list` as the default value
|
||||||
|
isInverted={isInverted}
|
||||||
|
>
|
||||||
|
{string}
|
||||||
|
</Tag>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tags.displayName = 'Tags';
|
export { Tags };
|
||||||
|
|
||||||
function StringTags({ children, strings, ...props }: StringTagsProps) {
|
|
||||||
const tags: TagData[] = strings.map((item) => ({
|
|
||||||
name: item,
|
|
||||||
}));
|
|
||||||
return (
|
|
||||||
<Tags tags={tags} {...props}>
|
|
||||||
{children}
|
|
||||||
</Tags>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
StringTags.displayName = 'StringTags';
|
|
||||||
|
|
||||||
function SegmentTags({ children, segments, ...props }: SegmentTagsProps) {
|
|
||||||
const tags: TagData[] = segments.map((segment) => ({
|
|
||||||
name: segment.name,
|
|
||||||
target: segment.id
|
|
||||||
? `admin.php?page=mailpoet-subscribers#/filter[segment=${segment.id}]`
|
|
||||||
: undefined,
|
|
||||||
tooltip: MailPoet.I18n.t('viewFilteredSubscribersMessage'),
|
|
||||||
}));
|
|
||||||
return (
|
|
||||||
<Tags tags={tags} {...props}>
|
|
||||||
{children}
|
|
||||||
</Tags>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
SegmentTags.displayName = 'SegmentTags';
|
|
||||||
|
|
||||||
function SubscriberTags({
|
|
||||||
children,
|
|
||||||
subscribers,
|
|
||||||
...props
|
|
||||||
}: SubscriberTagsProps) {
|
|
||||||
const tags: TagData[] = subscribers.map((item) => ({
|
|
||||||
name: item.name,
|
|
||||||
target: `admin.php?page=mailpoet-subscribers#/filter[tag=${item.tag_id}]`,
|
|
||||||
tooltip: MailPoet.I18n.t('viewFilteredSubscribersMessage'),
|
|
||||||
}));
|
|
||||||
return (
|
|
||||||
<Tags tags={tags} {...props}>
|
|
||||||
{children}
|
|
||||||
</Tags>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
SubscriberTags.displayName = 'SubscriberTags';
|
|
||||||
export { SegmentTags, StringTags, SubscriberTags };
|
|
||||||
|
@ -5,54 +5,36 @@ import { MailPoetLogoMobile } from './mailpoet_logo_mobile';
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
withLink?: boolean;
|
|
||||||
};
|
};
|
||||||
export function MailPoetLogoResponsive({ onClick, withLink = true }: Props) {
|
export function MailPoetLogoResponsive({ onClick }: Props) {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
let logo;
|
|
||||||
let onLogoClick = onClick;
|
let onLogoClick = onClick;
|
||||||
if (!onClick) {
|
if (!onClick) {
|
||||||
onLogoClick = () => history.push('/');
|
onLogoClick = () => history.push('/');
|
||||||
}
|
}
|
||||||
|
return (
|
||||||
if (withLink) {
|
<a
|
||||||
logo = (
|
role="button"
|
||||||
<a
|
className="mailpoet-top-bar-logo"
|
||||||
role="button"
|
title={t('topBarLogoTitle')}
|
||||||
className="mailpoet-top-bar-logo"
|
onClick={onLogoClick}
|
||||||
title={t('topBarLogoTitle')}
|
tabIndex={0}
|
||||||
onClick={onLogoClick}
|
onKeyDown={(event) => {
|
||||||
tabIndex={0}
|
if (
|
||||||
onKeyDown={(event) => {
|
['keydown', 'keypress'].includes(event.type) &&
|
||||||
if (
|
['Enter', ' '].includes(event.key)
|
||||||
['keydown', 'keypress'].includes(event.type) &&
|
) {
|
||||||
['Enter', ' '].includes(event.key)
|
event.preventDefault();
|
||||||
) {
|
onLogoClick();
|
||||||
event.preventDefault();
|
}
|
||||||
onLogoClick();
|
}}
|
||||||
}
|
>
|
||||||
}}
|
<div className="mailpoet-top-bar-logo-desktop">
|
||||||
>
|
<MailPoetLogo />
|
||||||
<div className="mailpoet-top-bar-logo-desktop">
|
|
||||||
<MailPoetLogo />
|
|
||||||
</div>
|
|
||||||
<div className="mailpoet-top-bar-logo-mobile">
|
|
||||||
<MailPoetLogoMobile />
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
logo = (
|
|
||||||
<div className="mailpoet-top-bar-logo">
|
|
||||||
<div className="mailpoet-top-bar-logo-desktop">
|
|
||||||
<MailPoetLogo />
|
|
||||||
</div>
|
|
||||||
<div className="mailpoet-top-bar-logo-mobile">
|
|
||||||
<MailPoetLogoMobile />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
<div className="mailpoet-top-bar-logo-mobile">
|
||||||
}
|
<MailPoetLogoMobile />
|
||||||
|
</div>
|
||||||
return logo;
|
</a>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -5,28 +5,21 @@ import { withFeatureAnnouncement } from 'announcements/with_feature_announcement
|
|||||||
import { MailPoetLogoResponsive } from './mailpoet_logo_responsive';
|
import { MailPoetLogoResponsive } from './mailpoet_logo_responsive';
|
||||||
import { BeamerIcon } from './beamer_icon';
|
import { BeamerIcon } from './beamer_icon';
|
||||||
import { ScreenOptionsFix } from './screen_options_fix';
|
import { ScreenOptionsFix } from './screen_options_fix';
|
||||||
import { withBoundary } from '../error_boundary';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
hasNews?: boolean;
|
hasNews?: boolean;
|
||||||
onBeamerClick?: () => void;
|
onBeamerClick?: () => void;
|
||||||
logoWithLink?: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export function TopBar({
|
export function TopBar({ children, hasNews, onBeamerClick }: Props) {
|
||||||
children,
|
|
||||||
hasNews,
|
|
||||||
onBeamerClick,
|
|
||||||
logoWithLink = true,
|
|
||||||
}: Props) {
|
|
||||||
const buttonClasses = classnames(
|
const buttonClasses = classnames(
|
||||||
'mailpoet-top-bar-beamer',
|
'mailpoet-top-bar-beamer',
|
||||||
hasNews ? 'mailpoet-top-bar-beamer-dot' : '',
|
hasNews ? 'mailpoet-top-bar-beamer-dot' : '',
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<div className="mailpoet-top-bar">
|
<div className="mailpoet-top-bar">
|
||||||
<MailPoetLogoResponsive withLink={logoWithLink} />
|
<MailPoetLogoResponsive />
|
||||||
<div className="mailpoet-top-bar-children">{children}</div>
|
<div className="mailpoet-top-bar-children">{children}</div>
|
||||||
<div className="mailpoet-flex-grow" />
|
<div className="mailpoet-flex-grow" />
|
||||||
{onBeamerClick && (
|
{onBeamerClick && (
|
||||||
@ -58,5 +51,4 @@ export function TopBar({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
TopBar.displayName = 'TopBar';
|
export const TopBarWithBeamer = withFeatureAnnouncement(TopBar);
|
||||||
export const TopBarWithBeamer = withFeatureAnnouncement(withBoundary(TopBar));
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import { MailPoet } from 'mailpoet';
|
import { MailPoet } from 'mailpoet';
|
||||||
import { GlobalContext, useGlobalContextValue } from 'context/index.jsx';
|
import { GlobalContext, useGlobalContextValue } from 'context/index.jsx';
|
||||||
import { Notices } from 'notices/notices.jsx';
|
import { Notices } from 'notices/notices.jsx';
|
||||||
import { ErrorBoundary } from 'common';
|
|
||||||
|
|
||||||
function ExperimentalFeatures() {
|
function ExperimentalFeatures() {
|
||||||
const [flags, setFlags] = useState(null);
|
const [flags, setFlags] = useState(null);
|
||||||
@ -107,14 +106,6 @@ function ExperimentalFeatures() {
|
|||||||
const experimentalFeaturesContainer = document.getElementById(
|
const experimentalFeaturesContainer = document.getElementById(
|
||||||
'experimental_features_container',
|
'experimental_features_container',
|
||||||
);
|
);
|
||||||
|
|
||||||
ExperimentalFeatures.displayName = 'ExperimentalFeatures';
|
|
||||||
|
|
||||||
if (experimentalFeaturesContainer) {
|
if (experimentalFeaturesContainer) {
|
||||||
ReactDOM.render(
|
ReactDOM.render(<ExperimentalFeatures />, experimentalFeaturesContainer);
|
||||||
<ErrorBoundary>
|
|
||||||
<ExperimentalFeatures />
|
|
||||||
</ErrorBoundary>,
|
|
||||||
experimentalFeaturesContainer,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { TokenFieldProps, TokenField } from 'common/form/tokenField/tokenField';
|
import { TokenFieldProps, TokenField } from 'common/form/tokenField/tokenField';
|
||||||
import { FormTokenItem } from '../../automation/editor/components';
|
import { FormTokenItem } from '../../automation/integrations/mailpoet/components/form-token-field';
|
||||||
|
|
||||||
interface TokenFormFieldProps {
|
interface TokenFormFieldProps {
|
||||||
onValueChange: TokenFieldProps['onChange'];
|
onValueChange: TokenFieldProps['onChange'];
|
||||||
|
@ -24,19 +24,8 @@ class FormComponent extends Component {
|
|||||||
this.loadItem(this.props.params.id);
|
this.loadItem(this.props.params.id);
|
||||||
} else {
|
} else {
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
const defaultValues =
|
|
||||||
jQuery('.mailpoet_form').mailpoetSerializeObject();
|
|
||||||
const checkboxField =
|
|
||||||
Array.isArray(this.props.fields) &&
|
|
||||||
this.props.fields.length > 0 &&
|
|
||||||
this.props.fields.find(
|
|
||||||
(field) => field?.type === 'checkbox' && field?.isChecked,
|
|
||||||
);
|
|
||||||
if (checkboxField && checkboxField.name) {
|
|
||||||
defaultValues[checkboxField.name] = '1';
|
|
||||||
}
|
|
||||||
this.setState({
|
this.setState({
|
||||||
item: defaultValues,
|
item: jQuery('.mailpoet_form').mailpoetSerializeObject(),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import PanelColorGradientSettings from '@wordpress/block-editor/build-module/components/colors-gradients/panel-color-gradient-settings';
|
import PanelColorGradientSettings from '@wordpress/block-editor/build-module/components/colors-gradients/panel-color-gradient-settings';
|
||||||
import { useSetting } from '@wordpress/block-editor';
|
import { useSetting } from '@wordpress/block-editor';
|
||||||
import { withBoundary } from 'common';
|
|
||||||
|
|
||||||
type Setting = {
|
type Setting = {
|
||||||
label: string;
|
label: string;
|
||||||
@ -15,7 +14,7 @@ type Props = {
|
|||||||
settings: Setting[];
|
settings: Setting[];
|
||||||
};
|
};
|
||||||
|
|
||||||
function ColorGradientSettings({ title, settings }: Props): JSX.Element {
|
export function ColorGradientSettings({ title, settings }: Props): JSX.Element {
|
||||||
const settingsColors = useSetting('color.palette');
|
const settingsColors = useSetting('color.palette');
|
||||||
const settingsGradients = useSetting('color.gradients');
|
const settingsGradients = useSetting('color.gradients');
|
||||||
return (
|
return (
|
||||||
@ -29,7 +28,3 @@ function ColorGradientSettings({ title, settings }: Props): JSX.Element {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorGradientSettings.displayName = 'ColorGradientSettings';
|
|
||||||
const ColorGradientSettingsWithBoundary = withBoundary(ColorGradientSettings);
|
|
||||||
export { ColorGradientSettingsWithBoundary as ColorGradientSettings };
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import '@wordpress/core-data';
|
import '@wordpress/core-data';
|
||||||
import { useDispatch, useSelect } from '@wordpress/data';
|
import { useSelect, useDispatch } from '@wordpress/data';
|
||||||
import { Popover, SlotFillProvider } from '@wordpress/components';
|
import { Popover, SlotFillProvider } from '@wordpress/components';
|
||||||
import { uploadMedia } from '@wordpress/media-utils';
|
import { uploadMedia } from '@wordpress/media-utils';
|
||||||
import {
|
import {
|
||||||
@ -9,14 +9,13 @@ import {
|
|||||||
BlockList,
|
BlockList,
|
||||||
BlockSelectionClearer,
|
BlockSelectionClearer,
|
||||||
BlockTools,
|
BlockTools,
|
||||||
|
WritingFlow,
|
||||||
ObserveTyping,
|
ObserveTyping,
|
||||||
SETTINGS_DEFAULTS,
|
SETTINGS_DEFAULTS,
|
||||||
WritingFlow,
|
|
||||||
} from '@wordpress/block-editor';
|
} from '@wordpress/block-editor';
|
||||||
import { ShortcutProvider } from '@wordpress/keyboard-shortcuts';
|
import { ShortcutProvider } from '@wordpress/keyboard-shortcuts';
|
||||||
|
|
||||||
import { UnsavedChangesNotice } from 'common/notices/unsaved_changes_notice.jsx';
|
import { UnsavedChangesNotice } from 'common/notices/unsaved_changes_notice.jsx';
|
||||||
import { ErrorBoundary } from 'common';
|
|
||||||
import { fetchLinkSuggestions } from '../utils/link_suggestions';
|
import { fetchLinkSuggestions } from '../utils/link_suggestions';
|
||||||
import { Header } from './header.jsx';
|
import { Header } from './header.jsx';
|
||||||
import { Tutorial } from './tutorial';
|
import { Tutorial } from './tutorial';
|
||||||
@ -114,12 +113,10 @@ export function Editor() {
|
|||||||
<div className={layoutClass}>
|
<div className={layoutClass}>
|
||||||
<div className="interface-interface-skeleton__editor">
|
<div className="interface-interface-skeleton__editor">
|
||||||
<div className="interface-interface-skeleton__header">
|
<div className="interface-interface-skeleton__header">
|
||||||
<ErrorBoundary>
|
<Header
|
||||||
<Header
|
isInserterOpened={isInserterOpened}
|
||||||
isInserterOpened={isInserterOpened}
|
setIsInserterOpened={toggleInserter}
|
||||||
setIsInserterOpened={toggleInserter}
|
/>
|
||||||
/>
|
|
||||||
</ErrorBoundary>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="interface-interface-skeleton__body">
|
<div className="interface-interface-skeleton__body">
|
||||||
<BlockEditorProvider
|
<BlockEditorProvider
|
||||||
@ -135,9 +132,7 @@ export function Editor() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="interface-interface-skeleton__content">
|
<div className="interface-interface-skeleton__content">
|
||||||
<ErrorBoundary>
|
<Notices />
|
||||||
<Notices />
|
|
||||||
</ErrorBoundary>
|
|
||||||
<UnsavedChangesNotice storeName="mailpoet-form-editor" />
|
<UnsavedChangesNotice storeName="mailpoet-form-editor" />
|
||||||
<BlockSelectionClearer className="edit-post-visual-editor editor-styles-wrapper">
|
<BlockSelectionClearer className="edit-post-visual-editor editor-styles-wrapper">
|
||||||
<BlockTools>
|
<BlockTools>
|
||||||
@ -146,11 +141,9 @@ export function Editor() {
|
|||||||
<div className="mailpoet_form">
|
<div className="mailpoet_form">
|
||||||
<WritingFlow>
|
<WritingFlow>
|
||||||
<ObserveTyping>
|
<ObserveTyping>
|
||||||
<ErrorBoundary>
|
<FormStylingBackground>
|
||||||
<FormStylingBackground>
|
<BlockList />
|
||||||
<BlockList />
|
</FormStylingBackground>
|
||||||
</FormStylingBackground>
|
|
||||||
</ErrorBoundary>
|
|
||||||
</ObserveTyping>
|
</ObserveTyping>
|
||||||
</WritingFlow>
|
</WritingFlow>
|
||||||
</div>
|
</div>
|
||||||
@ -159,27 +152,19 @@ export function Editor() {
|
|||||||
</div>
|
</div>
|
||||||
{sidebarOpened && (
|
{sidebarOpened && (
|
||||||
<div className="interface-interface-skeleton__sidebar">
|
<div className="interface-interface-skeleton__sidebar">
|
||||||
<ErrorBoundary>
|
<Sidebar />
|
||||||
<Sidebar />
|
|
||||||
</ErrorBoundary>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</BlockEditorProvider>
|
</BlockEditorProvider>
|
||||||
</div>
|
</div>
|
||||||
<ErrorBoundary>
|
<FormStyles />
|
||||||
<FormStyles />
|
<Fullscreen />
|
||||||
</ErrorBoundary>
|
|
||||||
<ErrorBoundary>
|
|
||||||
<Fullscreen />
|
|
||||||
</ErrorBoundary>
|
|
||||||
</div>
|
</div>
|
||||||
<Popover.Slot />
|
<Popover.Slot />
|
||||||
</div>
|
</div>
|
||||||
</SlotFillProvider>
|
</SlotFillProvider>
|
||||||
</ShortcutProvider>
|
</ShortcutProvider>
|
||||||
<ErrorBoundary>
|
<FormPreview />
|
||||||
<FormPreview />
|
|
||||||
</ErrorBoundary>
|
|
||||||
<Tutorial />
|
<Tutorial />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -3,9 +3,9 @@ import {
|
|||||||
Panel,
|
Panel,
|
||||||
PanelBody,
|
PanelBody,
|
||||||
RadioControl,
|
RadioControl,
|
||||||
SelectControl,
|
|
||||||
TextareaControl,
|
TextareaControl,
|
||||||
ToggleControl,
|
ToggleControl,
|
||||||
|
SelectControl,
|
||||||
} from '@wordpress/components';
|
} from '@wordpress/components';
|
||||||
import { useDispatch, useSelect } from '@wordpress/data';
|
import { useDispatch, useSelect } from '@wordpress/data';
|
||||||
import { MailPoet } from 'mailpoet';
|
import { MailPoet } from 'mailpoet';
|
||||||
@ -168,5 +168,5 @@ BasicSettingsPanel.propTypes = {
|
|||||||
onToggle: PropTypes.func.isRequired,
|
onToggle: PropTypes.func.isRequired,
|
||||||
isOpened: PropTypes.bool.isRequired,
|
isOpened: PropTypes.bool.isRequired,
|
||||||
};
|
};
|
||||||
BasicSettingsPanel.displayName = 'FormEditorBasicSettingsPanel';
|
|
||||||
export { BasicSettingsPanel };
|
export { BasicSettingsPanel };
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { ErrorBoundary } from 'common';
|
|
||||||
import { BelowPostsSettings } from './settings_panels/below_posts_settings';
|
import { BelowPostsSettings } from './settings_panels/below_posts_settings';
|
||||||
import { PopUpSettings } from './settings_panels/popup_settings';
|
import { PopUpSettings } from './settings_panels/popup_settings';
|
||||||
import { OtherSettings } from './settings_panels/other_settings';
|
import { OtherSettings } from './settings_panels/other_settings';
|
||||||
@ -12,31 +11,11 @@ type Props = {
|
|||||||
export function SettingsPanel({ activePanel }: Props): JSX.Element {
|
export function SettingsPanel({ activePanel }: Props): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div className="mailpoet-styles-settings">
|
<div className="mailpoet-styles-settings">
|
||||||
{activePanel === 'others' && (
|
{activePanel === 'others' && <OtherSettings />}
|
||||||
<ErrorBoundary>
|
{activePanel === 'below_posts' && <BelowPostsSettings />}
|
||||||
<OtherSettings />
|
{activePanel === 'fixed_bar' && <FixedBarSettings />}
|
||||||
</ErrorBoundary>
|
{activePanel === 'popup' && <PopUpSettings />}
|
||||||
)}
|
{activePanel === 'slide_in' && <SlideInSettings />}
|
||||||
{activePanel === 'below_posts' && (
|
|
||||||
<ErrorBoundary>
|
|
||||||
<BelowPostsSettings />
|
|
||||||
</ErrorBoundary>
|
|
||||||
)}
|
|
||||||
{activePanel === 'fixed_bar' && (
|
|
||||||
<ErrorBoundary>
|
|
||||||
<FixedBarSettings />
|
|
||||||
</ErrorBoundary>
|
|
||||||
)}
|
|
||||||
{activePanel === 'popup' && (
|
|
||||||
<ErrorBoundary>
|
|
||||||
<PopUpSettings />
|
|
||||||
</ErrorBoundary>
|
|
||||||
)}
|
|
||||||
{activePanel === 'slide_in' && (
|
|
||||||
<ErrorBoundary>
|
|
||||||
<SlideInSettings />
|
|
||||||
</ErrorBoundary>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,14 @@ import { MailPoet } from 'mailpoet';
|
|||||||
import { __, assocPath, compose } from 'lodash/fp';
|
import { __, assocPath, compose } from 'lodash/fp';
|
||||||
import { useDispatch, useSelect } from '@wordpress/data';
|
import { useDispatch, useSelect } from '@wordpress/data';
|
||||||
import { SelectControl } from '@wordpress/components';
|
import { SelectControl } from '@wordpress/components';
|
||||||
import { withBoundary } from 'common';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
settingsPlacementKey: string;
|
settingsPlacementKey: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
function AnimationSettings({ settingsPlacementKey }: Props): JSX.Element {
|
export function AnimationSettings({
|
||||||
|
settingsPlacementKey,
|
||||||
|
}: Props): JSX.Element {
|
||||||
const formSettings = useSelect(
|
const formSettings = useSelect(
|
||||||
(select) => select('mailpoet-form-editor').getFormSettings(),
|
(select) => select('mailpoet-form-editor').getFormSettings(),
|
||||||
[],
|
[],
|
||||||
@ -41,7 +42,3 @@ function AnimationSettings({ settingsPlacementKey }: Props): JSX.Element {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimationSettings.displayName = 'FormEditorAnimationSettings';
|
|
||||||
const AnimationSettingsWithBoundary = withBoundary(AnimationSettings);
|
|
||||||
export { AnimationSettingsWithBoundary as AnimationSettings };
|
|
||||||
|
@ -2,13 +2,12 @@ import { MailPoet } from 'mailpoet';
|
|||||||
import { __, assocPath, compose } from 'lodash/fp';
|
import { __, assocPath, compose } from 'lodash/fp';
|
||||||
import { useDispatch, useSelect } from '@wordpress/data';
|
import { useDispatch, useSelect } from '@wordpress/data';
|
||||||
import { SelectControl } from '@wordpress/components';
|
import { SelectControl } from '@wordpress/components';
|
||||||
import { withBoundary } from 'common';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
settingsPlacementKey: string;
|
settingsPlacementKey: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
function CookieSettings({ settingsPlacementKey }: Props): JSX.Element {
|
export function CookieSettings({ settingsPlacementKey }: Props): JSX.Element {
|
||||||
const cookieExpirationValues = [3, 7, 14, 30, 60, 90];
|
const cookieExpirationValues = [3, 7, 14, 30, 60, 90];
|
||||||
const formSettings = useSelect(
|
const formSettings = useSelect(
|
||||||
(select) => select('mailpoet-form-editor').getFormSettings(),
|
(select) => select('mailpoet-form-editor').getFormSettings(),
|
||||||
@ -48,7 +47,3 @@ function CookieSettings({ settingsPlacementKey }: Props): JSX.Element {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
CookieSettings.displayName = 'FormEditorCookieSettings';
|
|
||||||
const CookieSettingsWithBoundary = withBoundary(CookieSettings);
|
|
||||||
export { CookieSettingsWithBoundary as CookieSettings };
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user