Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
3e2ffdc848 |
@ -71,13 +71,6 @@ anchors:
|
|||||||
- trunk
|
- trunk
|
||||||
- release
|
- release
|
||||||
|
|
||||||
only_trunk_and_cot: &only_trunk_and_cot
|
|
||||||
filters:
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- trunk
|
|
||||||
- /^cot-.*/
|
|
||||||
|
|
||||||
multisite_acceptance_config: &multisite_acceptance_config
|
multisite_acceptance_config: &multisite_acceptance_config
|
||||||
multisite: 1
|
multisite: 1
|
||||||
requires:
|
requires:
|
||||||
@ -99,7 +92,7 @@ executors:
|
|||||||
wpcli_php_latest:
|
wpcli_php_latest:
|
||||||
<<: *default_job_config
|
<<: *default_job_config
|
||||||
docker:
|
docker:
|
||||||
- image: mailpoet/wordpress:8.1_20220718.1
|
- image: mailpoet/wordpress:8.1_20220309.1
|
||||||
|
|
||||||
wpcli_php_mysql_oldest:
|
wpcli_php_mysql_oldest:
|
||||||
<<: *default_job_config
|
<<: *default_job_config
|
||||||
@ -110,7 +103,7 @@ executors:
|
|||||||
wpcli_php_mysql_latest:
|
wpcli_php_mysql_latest:
|
||||||
<<: *default_job_config
|
<<: *default_job_config
|
||||||
docker:
|
docker:
|
||||||
- image: mailpoet/wordpress:8.1_20220718.1
|
- image: mailpoet/wordpress:8.1_20220309.1
|
||||||
- image: cimg/mysql:8.0
|
- image: cimg/mysql:8.0
|
||||||
command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_520_ci
|
command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_520_ci
|
||||||
|
|
||||||
@ -122,9 +115,6 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- checkout:
|
- checkout:
|
||||||
path: /home/circleci/mailpoet
|
path: /home/circleci/mailpoet
|
||||||
- run:
|
|
||||||
name: 'Set PNPM store directory'
|
|
||||||
command: pnpm config set store-dir ~/.pnpm-store
|
|
||||||
- run:
|
- run:
|
||||||
name: 'Compute checksum for prefixer'
|
name: 'Compute checksum for prefixer'
|
||||||
command: find prefixer -type f -not -path 'prefixer/build/*' -not -path 'prefixer/vendor/*' | sort | xargs cat | sha512sum > prefixer-checksum
|
command: find prefixer -type f -not -path 'prefixer/build/*' -not -path 'prefixer/vendor/*' | sort | xargs cat | sha512sum > prefixer-checksum
|
||||||
@ -140,8 +130,8 @@ jobs:
|
|||||||
key: composer-prefixed-{{ checksum "prefixer-checksum" }}
|
key: composer-prefixed-{{ checksum "prefixer-checksum" }}
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- pnpm-{{ checksum "../pnpm-lock.yaml" }}
|
- npm-{{ checksum "package-lock.json" }}
|
||||||
- pnpm- # fallback to most recent pnpm-* if not found by checksum
|
- npm- # fallback to most recent npm-* if not found by checksum
|
||||||
- run:
|
- run:
|
||||||
name: 'Set up test environment'
|
name: 'Set up test environment'
|
||||||
command: |
|
command: |
|
||||||
@ -180,32 +170,31 @@ jobs:
|
|||||||
- prefixer/vendor
|
- prefixer/vendor
|
||||||
- vendor-prefixed
|
- vendor-prefixed
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: pnpm-{{ checksum "../pnpm-lock.yaml" }}
|
key: npm-{{ checksum "package-lock.json" }}
|
||||||
paths:
|
paths:
|
||||||
- ~/.pnpm-store
|
- ~/.npm
|
||||||
- run:
|
- run:
|
||||||
name: Download additional WP Plugins for tests
|
name: Download additional WP Plugins for tests
|
||||||
command: |
|
command: |
|
||||||
./do download:woo-commerce-zip 6.8.2
|
./do download:woo-commerce-zip 6.2.0
|
||||||
./do download:woo-commerce-subscriptions-zip 4.5.1
|
./do download:woo-commerce-subscriptions-zip 3.0.14
|
||||||
./do download:woo-commerce-memberships-zip 1.23.0
|
./do download:woo-commerce-memberships-zip 1.22.9
|
||||||
./do download:woo-commerce-blocks-zip 8.4.0
|
./do download:woo-commerce-blocks-zip 7.2.1
|
||||||
- run:
|
- run:
|
||||||
name: Dump tests ENV variables for acceptance tests
|
name: Dump tests ENV variables for acceptance tests
|
||||||
command: |
|
command: |
|
||||||
(printenv | grep WP_TEST_ > .env) || true
|
(printenv | grep WP_TEST_ > .env) || true
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
root: /home/circleci
|
root: /home/circleci/mailpoet
|
||||||
paths:
|
paths:
|
||||||
- .node
|
- .
|
||||||
- mailpoet
|
|
||||||
build_premium:
|
build_premium:
|
||||||
executor: wpcli_php_latest
|
executor: wpcli_php_latest
|
||||||
resource_class: medium
|
resource_class: medium
|
||||||
working_directory: /home/circleci/mailpoet
|
working_directory: /home/circleci/mailpoet
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
at: /home/circleci
|
at: /home/circleci/mailpoet
|
||||||
- add_ssh_keys
|
- add_ssh_keys
|
||||||
- run:
|
- run:
|
||||||
name: 'Install Premium plugin'
|
name: 'Install Premium plugin'
|
||||||
@ -237,11 +226,9 @@ jobs:
|
|||||||
paths:
|
paths:
|
||||||
- mailpoet-premium/vendor
|
- mailpoet-premium/vendor
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
root: /home/circleci
|
root: /home/circleci/mailpoet
|
||||||
paths:
|
paths:
|
||||||
- .node
|
- .
|
||||||
- mailpoet
|
|
||||||
|
|
||||||
static_analysis:
|
static_analysis:
|
||||||
executor: wpcli_php_latest
|
executor: wpcli_php_latest
|
||||||
resource_class: medium
|
resource_class: medium
|
||||||
@ -252,7 +239,7 @@ jobs:
|
|||||||
default: 70200
|
default: 70200
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
at: /home/circleci
|
at: /home/circleci/mailpoet
|
||||||
- run:
|
- run:
|
||||||
name: 'Static analysis'
|
name: 'Static analysis'
|
||||||
command: ./do qa:phpstan --php-version=<< parameters.php_version >>
|
command: ./do qa:phpstan --php-version=<< parameters.php_version >>
|
||||||
@ -261,7 +248,7 @@ jobs:
|
|||||||
working_directory: /home/circleci/mailpoet/mailpoet
|
working_directory: /home/circleci/mailpoet/mailpoet
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
at: /home/circleci
|
at: /home/circleci/mailpoet
|
||||||
- run:
|
- run:
|
||||||
name: 'QA Frontend Assets'
|
name: 'QA Frontend Assets'
|
||||||
command: ./do qa:frontend-assets
|
command: ./do qa:frontend-assets
|
||||||
@ -270,7 +257,7 @@ jobs:
|
|||||||
working_directory: /home/circleci/mailpoet/mailpoet
|
working_directory: /home/circleci/mailpoet/mailpoet
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
at: /home/circleci
|
at: /home/circleci/mailpoet
|
||||||
- run:
|
- run:
|
||||||
name: 'QA PHP'
|
name: 'QA PHP'
|
||||||
command: ./do qa:php
|
command: ./do qa:php
|
||||||
@ -279,7 +266,7 @@ jobs:
|
|||||||
working_directory: /home/circleci/mailpoet/mailpoet
|
working_directory: /home/circleci/mailpoet/mailpoet
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
at: /home/circleci
|
at: /home/circleci/mailpoet
|
||||||
- run:
|
- run:
|
||||||
name: 'QA PHP'
|
name: 'QA PHP'
|
||||||
command: ./do qa:php
|
command: ./do qa:php
|
||||||
@ -287,7 +274,7 @@ jobs:
|
|||||||
executor: wpcli_php_max_wporg
|
executor: wpcli_php_max_wporg
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
at: /home/circleci
|
at: /home/circleci/mailpoet
|
||||||
- run:
|
- run:
|
||||||
name: 'QA PHP'
|
name: 'QA PHP'
|
||||||
command: ./do qa:php-max-wporg
|
command: ./do qa:php-max-wporg
|
||||||
@ -296,7 +283,7 @@ jobs:
|
|||||||
working_directory: /home/circleci/mailpoet/mailpoet
|
working_directory: /home/circleci/mailpoet/mailpoet
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
at: /home/circleci
|
at: /home/circleci/mailpoet
|
||||||
- run:
|
- run:
|
||||||
name: 'Preparing test results folder'
|
name: 'Preparing test results folder'
|
||||||
command: mkdir test-results
|
command: mkdir test-results
|
||||||
@ -318,14 +305,11 @@ jobs:
|
|||||||
parallelism: 20
|
parallelism: 20
|
||||||
working_directory: /home/circleci/mailpoet/mailpoet
|
working_directory: /home/circleci/mailpoet/mailpoet
|
||||||
machine:
|
machine:
|
||||||
image: ubuntu-2204:2022.07.1
|
image: ubuntu-2004:202111-01
|
||||||
parameters:
|
parameters:
|
||||||
multisite:
|
multisite:
|
||||||
type: integer
|
type: integer
|
||||||
default: 0
|
default: 0
|
||||||
group:
|
|
||||||
type: string
|
|
||||||
default: ''
|
|
||||||
mysql_command:
|
mysql_command:
|
||||||
type: string
|
type: string
|
||||||
default: ''
|
default: ''
|
||||||
@ -350,15 +334,6 @@ jobs:
|
|||||||
woo_blocks_version:
|
woo_blocks_version:
|
||||||
type: string
|
type: string
|
||||||
default: ''
|
default: ''
|
||||||
enable_cot:
|
|
||||||
type: integer
|
|
||||||
default: 0
|
|
||||||
enable_cot_sync:
|
|
||||||
type: integer
|
|
||||||
default: 0
|
|
||||||
allow_fail:
|
|
||||||
type: integer
|
|
||||||
default: 0
|
|
||||||
environment:
|
environment:
|
||||||
MYSQL_COMMAND: << parameters.mysql_command >>
|
MYSQL_COMMAND: << parameters.mysql_command >>
|
||||||
MYSQL_IMAGE_VERSION: << parameters.mysql_image_version >>
|
MYSQL_IMAGE_VERSION: << parameters.mysql_image_version >>
|
||||||
@ -366,7 +341,7 @@ jobs:
|
|||||||
WORDPRESS_IMAGE_VERSION: << parameters.wordpress_image_version >>
|
WORDPRESS_IMAGE_VERSION: << parameters.wordpress_image_version >>
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
at: /home/circleci
|
at: /home/circleci/mailpoet
|
||||||
- run:
|
- run:
|
||||||
name: 'Set up virtual host'
|
name: 'Set up virtual host'
|
||||||
command: echo 127.0.0.1 mailpoet.loc | sudo tee -a /etc/hosts
|
command: echo 127.0.0.1 mailpoet.loc | sudo tee -a /etc/hosts
|
||||||
@ -410,52 +385,23 @@ jobs:
|
|||||||
name: Group acceptance tests
|
name: Group acceptance tests
|
||||||
command: |
|
command: |
|
||||||
# Convert test result filename values to be relative paths because the circleci CLI's split command requires exact matches
|
# Convert test result filename values to be relative paths because the circleci CLI's split command requires exact matches
|
||||||
if [ -e $CIRCLE_INTERNAL_TASK_DATA/circle-test-results/results.json ]; then
|
sed -i.bak 's#/wp-core/wp-content/plugins/mailpoet/##g' $CIRCLE_INTERNAL_TASK_DATA/circle-test-results/results.json
|
||||||
sed -i.bak 's#/wp-core/wp-content/plugins/mailpoet/##g' $CIRCLE_INTERNAL_TASK_DATA/circle-test-results/results.json
|
|
||||||
fi
|
|
||||||
# `circleci tests split` returns different values based on the container it's run on
|
# `circleci tests split` returns different values based on the container it's run on
|
||||||
# in case group is defined find only tests containing the group
|
circleci tests glob "tests/acceptance/**/*Cest.php" | circleci tests split --split-by=timings > tests/acceptance/_groups/circleci_split_group
|
||||||
if [[ -n '<< parameters.group >>' ]]; then
|
|
||||||
grep -rw 'tests/acceptance' -e '@group << parameters.group >>' | sed -e "s/:.*//" | circleci tests split --split-by=timings > tests/acceptance/_groups/circleci_split_group
|
|
||||||
else
|
|
||||||
circleci tests glob "tests/acceptance/**/*Cest.php" | circleci tests split --split-by=timings > tests/acceptance/_groups/circleci_split_group
|
|
||||||
fi
|
|
||||||
cat tests/acceptance/_groups/circleci_split_group
|
cat tests/acceptance/_groups/circleci_split_group
|
||||||
- run:
|
- run:
|
||||||
name: Run acceptance tests
|
name: Run acceptance tests
|
||||||
command: |
|
command: |
|
||||||
mkdir -m 777 -p tests/_output/exceptions
|
mkdir -m 777 -p tests/_output/exceptions
|
||||||
cd tests/docker
|
cd tests/docker
|
||||||
args=(
|
docker-compose run -e SKIP_DEPS=1 -e CIRCLE_BRANCH=${CIRCLE_BRANCH} -e CIRCLE_JOB=${CIRCLE_JOB} -e MULTISITE=<< parameters.multisite >> codeception_acceptance -g circleci_split_group --steps --debug -vvv --html --xml
|
||||||
--steps
|
- run:
|
||||||
--debug
|
name: Check exceptions
|
||||||
-vvv
|
command: |
|
||||||
--html
|
if [ "$(ls tests/_output/exceptions/*.html)" ]; then
|
||||||
--xml
|
echo "There were some exceptions during the tests run"
|
||||||
-g circleci_split_group
|
exit 1
|
||||||
)
|
|
||||||
if [[ << parameters.allow_fail >> == 1 ]]; then
|
|
||||||
args+=(--no-exit)
|
|
||||||
fi
|
fi
|
||||||
docker-compose run -e SKIP_DEPS=1 \
|
|
||||||
-e CIRCLE_BRANCH=${CIRCLE_BRANCH} \
|
|
||||||
-e CIRCLE_JOB=${CIRCLE_JOB} \
|
|
||||||
-e MULTISITE=<< parameters.multisite >> \
|
|
||||||
-e ENABLE_COT=<< parameters.enable_cot >> \
|
|
||||||
-e ENABLE_COT_SYNC=<< parameters.enable_cot_sync >> \
|
|
||||||
codeception_acceptance "${args[@]}"
|
|
||||||
- when:
|
|
||||||
condition:
|
|
||||||
not:
|
|
||||||
equal: [1, << parameters.allow_fail >>]
|
|
||||||
steps:
|
|
||||||
- run:
|
|
||||||
name: Check exceptions
|
|
||||||
command: |
|
|
||||||
if [ "$(ls tests/_output/exceptions/*.html)" ]; then
|
|
||||||
echo "There were some exceptions during the tests run"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: tests/_output
|
path: tests/_output
|
||||||
- store_test_results:
|
- store_test_results:
|
||||||
@ -469,7 +415,7 @@ jobs:
|
|||||||
executor: << parameters.executor >>
|
executor: << parameters.executor >>
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
at: /home/circleci
|
at: /home/circleci/mailpoet
|
||||||
- run:
|
- run:
|
||||||
name: 'Set up virtual host'
|
name: 'Set up virtual host'
|
||||||
command: echo 127.0.0.1 mailpoet.loc | sudo tee -a /etc/hosts
|
command: echo 127.0.0.1 mailpoet.loc | sudo tee -a /etc/hosts
|
||||||
@ -494,93 +440,48 @@ jobs:
|
|||||||
integration_tests:
|
integration_tests:
|
||||||
working_directory: /home/circleci/mailpoet/mailpoet
|
working_directory: /home/circleci/mailpoet/mailpoet
|
||||||
machine:
|
machine:
|
||||||
image: ubuntu-2204:2022.07.1
|
image: ubuntu-2004:202111-01
|
||||||
environment:
|
environment:
|
||||||
CODECEPTION_IMAGE_VERSION: << parameters.codeception_image_version >>
|
CODECEPTION_IMAGE_VERSION: << parameters.codeception_image_version >>
|
||||||
parameters:
|
parameters:
|
||||||
codeception_image_version:
|
codeception_image_version:
|
||||||
type: string
|
type: string
|
||||||
default: ''
|
default: ''
|
||||||
group:
|
|
||||||
type: string
|
|
||||||
default: ''
|
|
||||||
skip_group:
|
|
||||||
type: string
|
|
||||||
default: ''
|
|
||||||
skip_plugins:
|
|
||||||
type: integer
|
|
||||||
default: 0
|
|
||||||
enable_cot:
|
|
||||||
type: integer
|
|
||||||
default: 0
|
|
||||||
enable_cot_sync:
|
|
||||||
type: integer
|
|
||||||
default: 0
|
|
||||||
multisite:
|
multisite:
|
||||||
type: integer
|
type: integer
|
||||||
default: 0
|
default: 0
|
||||||
woo_core_version:
|
run_command:
|
||||||
type: string
|
type: string
|
||||||
default: ''
|
default: |
|
||||||
allow_fail:
|
mkdir -m 777 -p tests/_output/exceptions
|
||||||
type: integer
|
cd tests/docker
|
||||||
default: 0
|
docker-compose run -e SKIP_DEPS=1 \
|
||||||
|
-e CIRCLE_BRANCH=${CIRCLE_BRANCH} \
|
||||||
|
-e CIRCLE_JOB=${CIRCLE_JOB} \
|
||||||
|
-e WP_TEST_MAILER_ENABLE_SENDING=${WP_TEST_MAILER_ENABLE_SENDING} \
|
||||||
|
-e WP_TEST_ENABLE_NETWORK_TESTS=${WP_TEST_ENABLE_NETWORK_TESTS} \
|
||||||
|
-e WP_TEST_MAILER_MAILPOET_API=${WP_TEST_MAILER_MAILPOET_API} \
|
||||||
|
-e WP_TEST_MAILER_SENDGRID_API=${WP_TEST_MAILER_SENDGRID_API} \
|
||||||
|
-e WP_TEST_MAILER_AMAZON_ACCESS=${WP_TEST_MAILER_AMAZON_ACCESS} \
|
||||||
|
-e WP_TEST_MAILER_AMAZON_REGION=${WP_TEST_MAILER_AMAZON_REGION} \
|
||||||
|
-e WP_TEST_MAILER_AMAZON_SECRET=${WP_TEST_MAILER_AMAZON_SECRET} \
|
||||||
|
-e WP_TEST_IMPORT_MAILCHIMP_API=${WP_TEST_IMPORT_MAILCHIMP_API} \
|
||||||
|
-e WP_TEST_IMPORT_MAILCHIMP_LISTS=${WP_TEST_IMPORT_MAILCHIMP_LISTS} \
|
||||||
|
-e WP_TEST_MAILER_SMTP_HOST=${WP_TEST_MAILER_SMTP_HOST} \
|
||||||
|
-e WP_TEST_MAILER_SMTP_LOGIN=${WP_TEST_MAILER_SMTP_LOGIN} \
|
||||||
|
-e WP_TEST_MAILER_SMTP_PASSWORD=${WP_TEST_MAILER_SMTP_PASSWORD} \
|
||||||
|
-e MULTISITE=<< parameters.multisite >> \
|
||||||
|
codeception_integration --steps --debug -vvv --html --xml
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
at: /home/circleci
|
at: /home/circleci/mailpoet
|
||||||
- run:
|
- run:
|
||||||
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: << parameters.run_command >>
|
||||||
mkdir -m 777 -p tests/_output/exceptions
|
|
||||||
cd tests/docker
|
|
||||||
args=(
|
|
||||||
--steps
|
|
||||||
--debug
|
|
||||||
-vvv
|
|
||||||
--html
|
|
||||||
--xml
|
|
||||||
)
|
|
||||||
if [[ -n '<< parameters.group >>' ]]; then
|
|
||||||
args+=(--group << parameters.group >>)
|
|
||||||
fi
|
|
||||||
if [[ -n '<< parameters.skip_group >>' ]]; then
|
|
||||||
args+=(--skip-group << parameters.skip_group >>)
|
|
||||||
fi
|
|
||||||
if [[ << parameters.allow_fail >> == 1 ]]; then
|
|
||||||
args+=(--no-exit)
|
|
||||||
fi
|
|
||||||
docker-compose run -e SKIP_DEPS=1 \
|
|
||||||
-e CIRCLE_BRANCH=${CIRCLE_BRANCH} \
|
|
||||||
-e CIRCLE_JOB=${CIRCLE_JOB} \
|
|
||||||
-e SKIP_PLUGINS=<< parameters.skip_plugins >> \
|
|
||||||
-e WP_TEST_MAILER_ENABLE_SENDING=${WP_TEST_MAILER_ENABLE_SENDING} \
|
|
||||||
-e WP_TEST_ENABLE_NETWORK_TESTS=${WP_TEST_ENABLE_NETWORK_TESTS} \
|
|
||||||
-e WP_TEST_MAILER_MAILPOET_API=${WP_TEST_MAILER_MAILPOET_API} \
|
|
||||||
-e WP_TEST_MAILER_SENDGRID_API=${WP_TEST_MAILER_SENDGRID_API} \
|
|
||||||
-e WP_TEST_MAILER_AMAZON_ACCESS=${WP_TEST_MAILER_AMAZON_ACCESS} \
|
|
||||||
-e WP_TEST_MAILER_AMAZON_REGION=${WP_TEST_MAILER_AMAZON_REGION} \
|
|
||||||
-e WP_TEST_MAILER_AMAZON_SECRET=${WP_TEST_MAILER_AMAZON_SECRET} \
|
|
||||||
-e WP_TEST_IMPORT_MAILCHIMP_API=${WP_TEST_IMPORT_MAILCHIMP_API} \
|
|
||||||
-e WP_TEST_IMPORT_MAILCHIMP_LISTS=${WP_TEST_IMPORT_MAILCHIMP_LISTS} \
|
|
||||||
-e WP_TEST_MAILER_SMTP_HOST=${WP_TEST_MAILER_SMTP_HOST} \
|
|
||||||
-e WP_TEST_MAILER_SMTP_LOGIN=${WP_TEST_MAILER_SMTP_LOGIN} \
|
|
||||||
-e WP_TEST_MAILER_SMTP_PASSWORD=${WP_TEST_MAILER_SMTP_PASSWORD} \
|
|
||||||
-e MULTISITE=<< parameters.multisite >> \
|
|
||||||
-e ENABLE_COT=<< parameters.enable_cot >> \
|
|
||||||
-e ENABLE_COT_SYNC=<< parameters.enable_cot_sync >> \
|
|
||||||
codeception_integration "${args[@]}"
|
|
||||||
- store_test_results:
|
- store_test_results:
|
||||||
path: tests/_output
|
path: tests/_output
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
@ -594,7 +495,7 @@ jobs:
|
|||||||
resource_class: medium+
|
resource_class: medium+
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
at: /home/circleci
|
at: /home/circleci/mailpoet
|
||||||
- run:
|
- run:
|
||||||
name: 'Set up environment'
|
name: 'Set up environment'
|
||||||
command: |
|
command: |
|
||||||
@ -659,102 +560,12 @@ workflows:
|
|||||||
- static_analysis_php8
|
- static_analysis_php8
|
||||||
- qa_js
|
- qa_js
|
||||||
- qa_php
|
- qa_php
|
||||||
- acceptance_tests:
|
|
||||||
<<: *slack-fail-post-step
|
|
||||||
<<: *only_trunk_and_cot
|
|
||||||
name: acceptance_tests_woo_cot_sync
|
|
||||||
group: woo
|
|
||||||
enable_cot: 1
|
|
||||||
enable_cot_sync: 1
|
|
||||||
allow_fail: 1
|
|
||||||
woo_core_version: woo-cot-beta # Temporarily force COT beta version
|
|
||||||
requires:
|
|
||||||
- unit_tests
|
|
||||||
- static_analysis_php8
|
|
||||||
- qa_js
|
|
||||||
- qa_php
|
|
||||||
- acceptance_tests:
|
|
||||||
<<: *slack-fail-post-step
|
|
||||||
<<: *only_trunk_and_cot
|
|
||||||
name: acceptance_tests_woo_cot_no_sync
|
|
||||||
group: woo
|
|
||||||
enable_cot: 1
|
|
||||||
enable_cot_sync: 0
|
|
||||||
allow_fail: 1
|
|
||||||
woo_core_version: woo-cot-beta # Temporarily force COT beta version
|
|
||||||
requires:
|
|
||||||
- unit_tests
|
|
||||||
- static_analysis_php8
|
|
||||||
- qa_js
|
|
||||||
- qa_php
|
|
||||||
- acceptance_tests:
|
|
||||||
<<: *slack-fail-post-step
|
|
||||||
<<: *only_trunk_and_cot
|
|
||||||
name: acceptance_tests_woo_cot_off
|
|
||||||
group: woo
|
|
||||||
woo_core_version: woo-cot-beta # Temporarily force COT beta version
|
|
||||||
requires:
|
|
||||||
- unit_tests
|
|
||||||
- static_analysis_php8
|
|
||||||
- qa_js
|
|
||||||
- qa_php
|
|
||||||
- js_tests:
|
- js_tests:
|
||||||
<<: *slack-fail-post-step
|
<<: *slack-fail-post-step
|
||||||
requires:
|
requires:
|
||||||
- build
|
- build
|
||||||
- integration_tests:
|
- integration_tests:
|
||||||
<<: *slack-fail-post-step
|
<<: *slack-fail-post-step
|
||||||
group: woo
|
|
||||||
name: integration_test_woocommerce
|
|
||||||
requires:
|
|
||||||
- unit_tests
|
|
||||||
- static_analysis_php8
|
|
||||||
- qa_js
|
|
||||||
- qa_php
|
|
||||||
- integration_tests:
|
|
||||||
<<: *slack-fail-post-step
|
|
||||||
<<: *only_trunk_and_cot
|
|
||||||
group: woo
|
|
||||||
enable_cot: 1
|
|
||||||
enable_cot_sync: 1
|
|
||||||
allow_fail: 1
|
|
||||||
woo_core_version: woo-cot-beta # Temporarily force COT beta version
|
|
||||||
name: integration_test_woo_cot_sync
|
|
||||||
requires:
|
|
||||||
- unit_tests
|
|
||||||
- static_analysis_php8
|
|
||||||
- qa_js
|
|
||||||
- qa_php
|
|
||||||
- integration_tests:
|
|
||||||
<<: *slack-fail-post-step
|
|
||||||
<<: *only_trunk_and_cot
|
|
||||||
group: woo
|
|
||||||
enable_cot: 1
|
|
||||||
enable_cot_sync: 0
|
|
||||||
allow_fail: 1
|
|
||||||
woo_core_version: woo-cot-beta # Temporarily force COT beta version
|
|
||||||
name: integration_test_woo_cot_no_sync
|
|
||||||
requires:
|
|
||||||
- unit_tests
|
|
||||||
- static_analysis_php8
|
|
||||||
- qa_js
|
|
||||||
- qa_php
|
|
||||||
- integration_tests:
|
|
||||||
<<: *slack-fail-post-step
|
|
||||||
<<: *only_trunk_and_cot
|
|
||||||
group: woo
|
|
||||||
woo_core_version: woo-cot-beta # Temporarily force COT beta version
|
|
||||||
name: integration_test_woo_cot_off
|
|
||||||
requires:
|
|
||||||
- unit_tests
|
|
||||||
- static_analysis_php8
|
|
||||||
- qa_js
|
|
||||||
- qa_php
|
|
||||||
- integration_tests:
|
|
||||||
<<: *slack-fail-post-step
|
|
||||||
skip_group: woo
|
|
||||||
skip_plugins: 1
|
|
||||||
name: integration_test_base
|
|
||||||
requires:
|
requires:
|
||||||
- unit_tests
|
- unit_tests
|
||||||
- static_analysis_php8
|
- static_analysis_php8
|
||||||
@ -781,8 +592,7 @@ workflows:
|
|||||||
- build
|
- build
|
||||||
- acceptance_tests
|
- acceptance_tests
|
||||||
- js_tests
|
- js_tests
|
||||||
- integration_test_woocommerce
|
- integration_tests
|
||||||
- integration_test_base
|
|
||||||
|
|
||||||
nightly:
|
nightly:
|
||||||
triggers:
|
triggers:
|
||||||
@ -808,9 +618,9 @@ workflows:
|
|||||||
<<: *slack-fail-post-step
|
<<: *slack-fail-post-step
|
||||||
name: acceptance_oldest
|
name: acceptance_oldest
|
||||||
woo_core_version: 6.2.2
|
woo_core_version: 6.2.2
|
||||||
woo_subscriptions_version: 4.3.0
|
woo_subscriptions_version: 3.0.10
|
||||||
woo_memberships_version: 1.21.0
|
woo_memberships_version: 1.22.9
|
||||||
woo_blocks_version: 5.3.2
|
woo_blocks_version: 5.5.1
|
||||||
mysql_command: --max_allowed_packet=100M
|
mysql_command: --max_allowed_packet=100M
|
||||||
mysql_image_version: 5.7.36
|
mysql_image_version: 5.7.36
|
||||||
codeception_image_version: 7.4-cli_20210126.1
|
codeception_image_version: 7.4-cli_20210126.1
|
||||||
|
23
.github/pull_request_template.md
vendored
23
.github/pull_request_template.md
vendored
@ -1,23 +0,0 @@
|
|||||||
## Description
|
|
||||||
|
|
||||||
_N/A_
|
|
||||||
|
|
||||||
## Code review notes
|
|
||||||
|
|
||||||
_N/A_
|
|
||||||
|
|
||||||
## QA notes
|
|
||||||
|
|
||||||
_N/A_
|
|
||||||
|
|
||||||
## Linked PRs
|
|
||||||
|
|
||||||
_N/A_
|
|
||||||
|
|
||||||
## Linked tickets
|
|
||||||
|
|
||||||
_N/A_
|
|
||||||
|
|
||||||
## After-merge notes
|
|
||||||
|
|
||||||
_N/A_
|
|
@ -6,7 +6,6 @@ _output
|
|||||||
composer.json
|
composer.json
|
||||||
composer.lock
|
composer.lock
|
||||||
node_modules
|
node_modules
|
||||||
pnpm-lock.yaml
|
|
||||||
vendor
|
vendor
|
||||||
vendor-prefixed
|
vendor-prefixed
|
||||||
/.mp_svn
|
/.mp_svn
|
||||||
|
10
README.md
10
README.md
@ -12,16 +12,6 @@ If you'd like to use the plugin code directly, see details in [the plugin's read
|
|||||||
3. Run `./do start` to start the stack.
|
3. Run `./do start` to start the stack.
|
||||||
4. Go to http://localhost:8888 to see the dashboard of the dev environment.
|
4. Go to http://localhost:8888 to see the dashboard of the dev environment.
|
||||||
|
|
||||||
## ✅ Additional dependencies
|
|
||||||
|
|
||||||
Even though it possible to run everything using Docker, in the development workflow,
|
|
||||||
it may be faster and more convenient to run some tasks outside the container. Therefore,
|
|
||||||
the following tools are recommended:
|
|
||||||
|
|
||||||
1. **PHP** as per `composer.json` requirements.
|
|
||||||
2. **Node.js**, as specified by `.nvmrc`. For automatic management use [nvm](https://github.com/nvm-sh/nvm), [FNM](https://github.com/Schniz/fnm), or [Volta](https://github.com/volta-cli/volta).
|
|
||||||
3. **pnpm**, as specified in `package.json`. For automatic setup enable [Corepack](https://nodejs.org/docs/latest-v17.x/api/corepack.html) using `corepack enable`.
|
|
||||||
|
|
||||||
## 🔍 PHPStorm setup for XDebug
|
## 🔍 PHPStorm setup for XDebug
|
||||||
|
|
||||||
In `Languages & Preferences > PHP > Servers` set path mappings:
|
In `Languages & Preferences > PHP > Servers` set path mappings:
|
||||||
|
@ -9,10 +9,9 @@ RUN apt-get update \
|
|||||||
&& docker-php-ext-install pdo_mysql \
|
&& docker-php-ext-install pdo_mysql \
|
||||||
&& pecl install xdebug-2.9.8 && \
|
&& pecl install xdebug-2.9.8 && \
|
||||||
\
|
\
|
||||||
# Install NodeJS, enable Corepack
|
# Install NodeJS + NPM
|
||||||
curl -sL https://deb.nodesource.com/setup_17.x | bash - && \
|
curl -sL https://deb.nodesource.com/setup_16.x | bash - && \
|
||||||
apt-get install -y nodejs build-essential && \
|
apt-get install -y nodejs build-essential && \
|
||||||
corepack enable && \
|
|
||||||
\
|
\
|
||||||
# Install WP-CLI
|
# Install WP-CLI
|
||||||
curl -o /usr/local/bin/wp https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && \
|
curl -o /usr/local/bin/wp https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && \
|
||||||
@ -36,6 +35,5 @@ RUN cat /tmp/xdebug.ini >> $XDEBUGINI_PATH
|
|||||||
# allow .htaccess files (between <Directory /var/www/> and </Directory>, which is WordPress installation)
|
# 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
|
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
|
# ensure existing content in /var/www/html respects UID and GID
|
||||||
RUN chown -R ${UID}:${GID} /var/www/html && \
|
RUN chown -R ${UID}:${GID} /var/www/html
|
||||||
mkdir -p /.node && chown -R ${UID}:${GID} /.node
|
|
||||||
|
@ -7,10 +7,9 @@ ARG GID=1000
|
|||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y git zlib1g-dev libzip-dev zip wget gnupg msmtp libpng-dev gettext subversion \
|
&& apt-get install -y git zlib1g-dev libzip-dev zip wget gnupg msmtp libpng-dev gettext subversion \
|
||||||
&& \
|
&& \
|
||||||
# Install NodeJS, enable Corepack
|
# Install NodeJS + NPM
|
||||||
curl -sL https://deb.nodesource.com/setup_17.x | bash - && \
|
curl -sL https://deb.nodesource.com/setup_16.x | bash - && \
|
||||||
apt-get install -y nodejs build-essential && \
|
apt-get install -y nodejs build-essential && \
|
||||||
corepack enable && \
|
|
||||||
\
|
\
|
||||||
# Install WP-CLI
|
# Install WP-CLI
|
||||||
curl -o /usr/local/bin/wp https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && \
|
curl -o /usr/local/bin/wp https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && \
|
||||||
@ -40,6 +39,5 @@ RUN docker-php-ext-install pdo_mysql
|
|||||||
# allow .htaccess files (between <Directory /var/www/> and </Directory>, which is WordPress installation)
|
# 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
|
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
|
# ensure existing content in /var/www/html respects UID and GID
|
||||||
RUN chown -R ${UID}:${GID} /var/www/html && \
|
RUN chown -R ${UID}:${GID} /var/www/html
|
||||||
mkdir -p /.node && chown -R ${UID}:${GID} /.node
|
|
||||||
|
@ -7,10 +7,9 @@ ARG GID=1000
|
|||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y git zlib1g-dev libzip-dev zip wget gnupg msmtp libpng-dev gettext subversion \
|
&& apt-get install -y git zlib1g-dev libzip-dev zip wget gnupg msmtp libpng-dev gettext subversion \
|
||||||
&& \
|
&& \
|
||||||
# Install NodeJS, enable Corepack
|
# Install NodeJS + NPM
|
||||||
curl -sL https://deb.nodesource.com/setup_17.x | bash - && \
|
curl -sL https://deb.nodesource.com/setup_16.x | bash - && \
|
||||||
apt-get install -y nodejs build-essential && \
|
apt-get install -y nodejs build-essential && \
|
||||||
corepack enable && \
|
|
||||||
\
|
\
|
||||||
# Install WP-CLI
|
# Install WP-CLI
|
||||||
curl -o /usr/local/bin/wp https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && \
|
curl -o /usr/local/bin/wp https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && \
|
||||||
@ -40,6 +39,5 @@ RUN docker-php-ext-install pdo_mysql
|
|||||||
# allow .htaccess files (between <Directory /var/www/> and </Directory>, which is WordPress installation)
|
# 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
|
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
|
# ensure existing content in /var/www/html respects UID and GID
|
||||||
RUN chown -R ${UID}:${GID} /var/www/html && \
|
RUN chown -R ${UID}:${GID} /var/www/html
|
||||||
mkdir -p /.node && chown -R ${UID}:${GID} /.node
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
# MailPoet – Documentation for Integrators
|
# MailPoet 3 - Documentation for Integrators
|
||||||
|
|
||||||
This is a place where we put documentation for developers who want to build an extension for MailPoet plugin.
|
This is a place where we put documentation for developers who want to build an extension for MailPoet 3 plugin.
|
||||||
If you are a user looking for a user guide please visit our [knowledge base](https://kb.mailpoet.com/).
|
If you are a user looking for a user guide please visit our [knowledge base](https://kb.mailpoet.com/).
|
||||||
|
|
||||||
## MailPoet API
|
## MailPoet API
|
||||||
|
|
||||||
MailPoet API is the officially supported way to integrate with the MailPoet plugin. It focuses on functionality for managing subscribers.
|
MailPoet API is the officially supported way to integrate with the MailPoet 3 plugin. It focuses on functionality for managing subscribers.
|
||||||
Developers integrating MailPoet functionality in their own plugins or projects are strongly discouraged against using other functions and classes within MailPoet codebase! We are continually refactoring as part of our rapid development process, and backward compatibility is not guaranteed.
|
Developers integrating MailPoet functionality in their own plugins or projects are strongly discouraged against using other functions and classes within MailPoet codebase! We are continually refactoring as part of our rapid development process, and backward compatibility is not guaranteed.
|
||||||
|
|
||||||
### Basics
|
### Basics
|
||||||
@ -30,12 +30,10 @@ Class `\MailPoet\API\API` becomes available once MailPoet plugin is loaded by Wo
|
|||||||
- [Add Subscriber Field (addSubscriberField)](api_methods/AddSubscriberField.md)
|
- [Add Subscriber Field (addSubscriberField)](api_methods/AddSubscriberField.md)
|
||||||
- [Get Lists (getLists)](api_methods/GetLists.md)
|
- [Get Lists (getLists)](api_methods/GetLists.md)
|
||||||
- [Get Subscriber (getSubscriber)](api_methods/GetSubscriber.md)
|
- [Get Subscriber (getSubscriber)](api_methods/GetSubscriber.md)
|
||||||
- [Get Subscribers (getSubscribers)](api_methods/GetSubscribers.md)
|
|
||||||
- [Get Subscribers Count (getSubscribersCount)](api_methods/GetSubscribersCount.md)
|
|
||||||
- [Get Subscriber Fields (getSubscriberFields)](api_methods/GetSubscriberFields.md)
|
- [Get Subscriber Fields (getSubscriberFields)](api_methods/GetSubscriberFields.md)
|
||||||
- [Is Setup Complete (isSetupComplete)](api_methods/IsSetupComplete.md)
|
- [Is Setup Complete (isSetupComplete)](api_methods/IsSetupComplete.md)
|
||||||
- [Subscribe to List (subscribeToList)](api_methods/SubscribeToList.md)
|
- [Subscribe to List (subscribeToList)](api_methods/SubscribeToList.md)
|
||||||
- [Subscribe to Lists (subscribeToLists)](api_methods/SubscribeToLists.md)
|
- [Subscribe to List (subscribeToLists)](api_methods/SubscribeToLists.md)
|
||||||
- [Unsubscribe from List (unsubscribeFromList)](api_methods/UnsubscribeFromList.md)
|
- [Unsubscribe from List (unsubscribeFromList)](api_methods/UnsubscribeFromList.md)
|
||||||
- [Unsubscribe from Lists (unsubscribeFromLists)](api_methods/UnsubscribeFromLists.md)
|
- [Unsubscribe from Lists (unsubscribeFromLists)](api_methods/UnsubscribeFromLists.md)
|
||||||
|
|
||||||
|
@ -35,7 +35,6 @@ This method throws an `\Exception` in the event a subscriber with a given email
|
|||||||
| source | string\|null | - | Possible values: `form`,`imported`,`administrator`,`api`,`wordpress_user`,`woocommerce_user`,`woocommerce_checkout`,`unknown`) |
|
| source | string\|null | - | Possible values: `form`,`imported`,`administrator`,`api`,`wordpress_user`,`woocommerce_user`,`woocommerce_checkout`,`unknown`) |
|
||||||
| count_confirmations | string | 11 chars | Counter for confirmation emails |
|
| count_confirmations | string | 11 chars | Counter for confirmation emails |
|
||||||
| subscriptions | array | - | List of subcriber subscriptions |
|
| subscriptions | array | - | List of subcriber subscriptions |
|
||||||
| tags | array | - | List of subcriber tags |
|
|
||||||
| cf\_{custom_field['id']} | string | 65K chars | A custom subscriber field value (see [Get Subscriber Fields](GetSubscriberFields.md) |
|
| cf\_{custom_field['id']} | string | 65K chars | A custom subscriber field value (see [Get Subscriber Fields](GetSubscriberFields.md) |
|
||||||
|
|
||||||
### Subscriber's subscription
|
### Subscriber's subscription
|
||||||
@ -49,17 +48,6 @@ This method throws an `\Exception` in the event a subscriber with a given email
|
|||||||
| created_at | string | - | UTC time of creation in 'Y-m-d H:i:s' format |
|
| created_at | string | - | UTC time of creation in 'Y-m-d H:i:s' format |
|
||||||
| updated_at | string | - | UTC time of last update in 'Y-m-d H:i:s' format |
|
| updated_at | string | - | UTC time of last update in 'Y-m-d H:i:s' format |
|
||||||
|
|
||||||
### Subscriber's tag
|
|
||||||
|
|
||||||
| Property | Type | Limits | Description |
|
|
||||||
| ------------- | ------ | -------- | ----------------------------------------------- |
|
|
||||||
| id | string | 11 chars | Id of relation |
|
|
||||||
| subscriber_id | string | 11 chars | Id of subscriber |
|
|
||||||
| tag_id | string | 11 chars | Id of a list |
|
|
||||||
| name | string | - | Name of a tag |
|
|
||||||
| created_at | string | - | UTC time of creation in 'Y-m-d H:i:s' format |
|
|
||||||
| updated_at | string | - | UTC time of last update in 'Y-m-d H:i:s' format |
|
|
||||||
|
|
||||||
### Response Example
|
### Response Example
|
||||||
|
|
||||||
```php
|
```php
|
||||||
@ -99,24 +87,6 @@ This method throws an `\Exception` in the event a subscriber with a given email
|
|||||||
'updated_at' => '2019-05-14 08:43:08',
|
'updated_at' => '2019-05-14 08:43:08',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
'tags' => [
|
|
||||||
0 => [
|
|
||||||
'id' => '2',
|
|
||||||
'subscriber_id' => '10',
|
|
||||||
'tag_id' => '1',
|
|
||||||
'name' => 'Alpha',
|
|
||||||
'created_at' => '2019-05-17 05:24:37',
|
|
||||||
'updated_at' => '2019-05-17 05:24:37',
|
|
||||||
],
|
|
||||||
1 => [
|
|
||||||
'id' => '4',
|
|
||||||
'subscriber_id' => '10',
|
|
||||||
'tag_id' => '5',
|
|
||||||
'name' => 'Beta',
|
|
||||||
'created_at' => '2020-03-07 15:21:37',
|
|
||||||
'updated_at' => '2020-03-07 15:21:37',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
'cf_1' => 'US',
|
'cf_1' => 'US',
|
||||||
'cf_2' => 'New York',
|
'cf_2' => 'New York',
|
||||||
];
|
];
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
[back to list](../Readme.md)
|
|
||||||
|
|
||||||
# Get Subscribers
|
|
||||||
|
|
||||||
## `array getSubscribers(array $filter = [], int $limit = 50, int $offset = 0)`
|
|
||||||
|
|
||||||
This method returns a list of subscribers. To see the subscriber data structure, please check [getSubscriber()](GetSubscriber.md) documentation.
|
|
||||||
|
|
||||||
## Arguments
|
|
||||||
|
|
||||||
| Argument | Type | Default | Description |
|
|
||||||
| ------------------ | ----- | ------- | --------------------------------------- |
|
|
||||||
| $filter (optional) | array | empty | Filters to retrieve subscribers |
|
|
||||||
| $limit (optional) | int | 50 | The number of results that are returned |
|
|
||||||
| $offset (optional) | int | 0 | From where to start returning data |
|
|
||||||
|
|
||||||
### Filter
|
|
||||||
|
|
||||||
Filter argument supports following array keys.
|
|
||||||
|
|
||||||
| Key | Type | Description |
|
|
||||||
| -------------- | ------------ | ----------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| status | string | Specific status of subscribers. One of values: `unconfirmed`, `subscribed`, `unsubscribed`, `bounced`, `inactive` |
|
|
||||||
| list_id | int | List id or dynamic segment id |
|
|
||||||
| min_updated_at | DateTime\int | DateTime object or timestamp of the minimal last update of subscribers |
|
|
@ -1,17 +0,0 @@
|
|||||||
[back to list](../Readme.md)
|
|
||||||
|
|
||||||
# Get Subscribers Count
|
|
||||||
|
|
||||||
## `int getSubscribersCount(array $filter = [])`
|
|
||||||
|
|
||||||
This method returns the count of subscribers by a filter.
|
|
||||||
|
|
||||||
## Arguments
|
|
||||||
|
|
||||||
| Argument | Type | Default | Description |
|
|
||||||
| ------------------ | ----- | ------- | -------------------------------------------- |
|
|
||||||
| $filter (optional) | array | empty | Filters to retrieve the count of subscribers |
|
|
||||||
|
|
||||||
### Filter
|
|
||||||
|
|
||||||
To see supported filters, please check [getSubscribers()](GetSubscribers.md) documentation.
|
|
@ -49,14 +49,10 @@ services:
|
|||||||
MAILPOET_DEV_SITE: 1
|
MAILPOET_DEV_SITE: 1
|
||||||
volumes:
|
volumes:
|
||||||
- './wordpress:/var/www/html'
|
- './wordpress:/var/www/html'
|
||||||
|
- './eslint-config:/var/www/html/wp-content/plugins/eslint-config'
|
||||||
- './tsconfig.base.json:/var/www/html/wp-content/plugins/tsconfig.base.json:ro'
|
- './tsconfig.base.json:/var/www/html/wp-content/plugins/tsconfig.base.json:ro'
|
||||||
- './package.json:/var/www/html/wp-content/plugins/package.json'
|
|
||||||
- './pnpm-lock.yaml:/var/www/html/wp-content/plugins/pnpm-lock.yaml'
|
|
||||||
- './pnpm-workspace.yaml:/var/www/html/wp-content/plugins/pnpm-workspace.yaml'
|
|
||||||
- './patches:/var/www/html/wp-content/plugins/patches'
|
|
||||||
- './mailpoet:/var/www/html/wp-content/plugins/mailpoet'
|
- './mailpoet:/var/www/html/wp-content/plugins/mailpoet'
|
||||||
- './mailpoet-premium:/var/www/html/wp-content/plugins/mailpoet-premium'
|
- './mailpoet-premium:/var/www/html/wp-content/plugins/mailpoet-premium'
|
||||||
- './packages:/var/www/html/wp-content/plugins/packages'
|
|
||||||
- './templates:/var/www/templates'
|
- './templates:/var/www/templates'
|
||||||
|
|
||||||
test_wordpress:
|
test_wordpress:
|
||||||
@ -80,9 +76,9 @@ services:
|
|||||||
WORDPRESS_DB_PASSWORD: wordpress
|
WORDPRESS_DB_PASSWORD: wordpress
|
||||||
PHP_IDE_CONFIG: 'serverName=Mailpoet'
|
PHP_IDE_CONFIG: 'serverName=Mailpoet'
|
||||||
volumes:
|
volumes:
|
||||||
|
- './eslint-config:/var/www/html/wp-content/plugins/eslint-config'
|
||||||
- './mailpoet:/var/www/html/wp-content/plugins/mailpoet'
|
- './mailpoet:/var/www/html/wp-content/plugins/mailpoet'
|
||||||
- './mailpoet-premium:/var/www/html/wp-content/plugins/mailpoet-premium'
|
- './mailpoet-premium:/var/www/html/wp-content/plugins/mailpoet-premium'
|
||||||
- './packages:/var/www/html/wp-content/plugins/packages'
|
|
||||||
|
|
||||||
smtp:
|
smtp:
|
||||||
container_name: mp-mailhog
|
container_name: mp-mailhog
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
"react-hooks/rules-of-hooks": "error",
|
"react-hooks/rules-of-hooks": "error",
|
||||||
"react-hooks/exhaustive-deps": "warn",
|
"react-hooks/exhaustive-deps": "warn",
|
||||||
// Exceptions
|
// Exceptions
|
||||||
"no-void": 0, // can conflict with @typescript-eslint/no-floating-promises
|
|
||||||
"react/jsx-filename-extension": 0,
|
"react/jsx-filename-extension": 0,
|
||||||
"@typescript-eslint/no-unsafe-return": 0, // we need to disable it for wordpress select :(
|
"@typescript-eslint/no-unsafe-return": 0, // we need to disable it for wordpress select :(
|
||||||
"@typescript-eslint/no-unsafe-member-access": 0, // we need to disable it for wordpress select :(
|
"@typescript-eslint/no-unsafe-member-access": 0, // we need to disable it for wordpress select :(
|
7057
eslint-config/package-lock.json
generated
Normal file
7057
eslint-config/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -19,8 +19,5 @@
|
|||||||
"eslint-plugin-no-only-tests": "^2.6.0",
|
"eslint-plugin-no-only-tests": "^2.6.0",
|
||||||
"eslint-plugin-react": "^7.28.0",
|
"eslint-plugin-react": "^7.28.0",
|
||||||
"eslint-plugin-react-hooks": "^4.3.0"
|
"eslint-plugin-react-hooks": "^4.3.0"
|
||||||
},
|
|
||||||
"volta": {
|
|
||||||
"extends": "../../../package.json"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,7 +5,9 @@
|
|||||||
"@babel/preset-env"
|
"@babel/preset-env"
|
||||||
],
|
],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
|
"@babel/plugin-proposal-nullish-coalescing-operator",
|
||||||
"babel-plugin-typescript-to-proptypes",
|
"babel-plugin-typescript-to-proptypes",
|
||||||
|
"@babel/plugin-proposal-class-properties",
|
||||||
[
|
[
|
||||||
"@babel/plugin-transform-runtime",
|
"@babel/plugin-transform-runtime",
|
||||||
{
|
{
|
||||||
@ -13,7 +15,18 @@
|
|||||||
"corejs": 3
|
"corejs": 3
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"@babel/plugin-syntax-dynamic-import",
|
||||||
|
"@babel/plugin-syntax-import-meta",
|
||||||
|
"@babel/plugin-proposal-json-strings",
|
||||||
|
[
|
||||||
|
"@babel/plugin-proposal-decorators",
|
||||||
|
{
|
||||||
|
"legacy": true
|
||||||
|
}
|
||||||
|
],
|
||||||
"@babel/plugin-proposal-function-sent",
|
"@babel/plugin-proposal-function-sent",
|
||||||
|
"@babel/plugin-proposal-export-namespace-from",
|
||||||
|
"@babel/plugin-proposal-numeric-separator",
|
||||||
"@babel/plugin-proposal-throw-expressions"
|
"@babel/plugin-proposal-throw-expressions"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
v17.9.1
|
v16.13.0
|
||||||
|
@ -23,7 +23,9 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
return $this->taskExecStack()
|
return $this->taskExecStack()
|
||||||
->stopOnFail()
|
->stopOnFail()
|
||||||
->exec('./tools/vendor/composer.phar install')
|
->exec('./tools/vendor/composer.phar install')
|
||||||
->exec('cd .. && pnpm install --frozen-lockfile --prefer-offline')
|
->exec('npm ci --prefer-offline')
|
||||||
|
->exec('cd .. && npm ci --prefer-offline')
|
||||||
|
->exec('cd ../eslint-config && npm ci --prefer-offline')
|
||||||
->addCode([$this, 'cleanupCachedFiles'])
|
->addCode([$this, 'cleanupCachedFiles'])
|
||||||
->run();
|
->run();
|
||||||
}
|
}
|
||||||
@ -39,7 +41,7 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
return $this->taskExecStack()
|
return $this->taskExecStack()
|
||||||
->stopOnFail()
|
->stopOnFail()
|
||||||
->exec('./tools/vendor/composer.phar update')
|
->exec('./tools/vendor/composer.phar update')
|
||||||
->exec('pnpm update')
|
->exec('npm update')
|
||||||
->run();
|
->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,8 +52,8 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
$file = $changedFile->getResource()->getResource();
|
$file = $changedFile->getResource()->getResource();
|
||||||
$this->taskExecStack()
|
$this->taskExecStack()
|
||||||
->stopOnFail()
|
->stopOnFail()
|
||||||
->exec('pnpm run scss')
|
->exec('npm run scss')
|
||||||
->exec('pnpm run autoprefixer')
|
->exec('npm run autoprefixer')
|
||||||
->run();
|
->run();
|
||||||
})
|
})
|
||||||
->run();
|
->run();
|
||||||
@ -90,11 +92,9 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
// Clean up folder from previous files
|
// Clean up folder from previous files
|
||||||
array_map('unlink', glob("assets/dist/css/*.*"));
|
array_map('unlink', glob("assets/dist/css/*.*"));
|
||||||
|
|
||||||
$compilationResult = $this->taskExecStack()
|
$this->_exec('npm run stylelint -- "assets/css/src/**/*.scss"');
|
||||||
->exec('pnpm run stylelint-check -- "assets/css/src/**/*.scss"')
|
$this->_exec('npm run scss');
|
||||||
->exec('pnpm run scss')
|
$compilationResult = $this->_exec('npm run autoprefixer');
|
||||||
->exec('pnpm run autoprefixer')
|
|
||||||
->run();
|
|
||||||
|
|
||||||
// Create manifest file
|
// Create manifest file
|
||||||
$manifest = [];
|
$manifest = [];
|
||||||
@ -184,20 +184,13 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
return $this->_exec($command);
|
return $this->_exec($command);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testIntegration(array $opts = ['file' => null, 'group' => null, 'skip-group' => null, 'xml' => false, 'multisite' => false, 'debug' => false, 'skip-deps' => false, 'skip-plugins' => false, 'enable-cot' => false, 'enable-cot-sync' => false]) {
|
public function testIntegration(array $opts = ['file' => null, 'xml' => false, 'multisite' => false, 'debug' => false, 'skip-deps' => false]) {
|
||||||
return $this->runTestsInContainer(array_merge($opts, ['test_type' => 'integration']));
|
return $this->runTestsInContainer(array_merge($opts, ['test_type' => 'integration']));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMultisiteIntegration($opts = ['file' => null, 'group' => null, 'skip-group' => null, 'xml' => false, 'multisite' => true, 'skip-deps' => false, 'skip-plugins' => false, 'enable-cot' => false, 'enable-cot-sync' => false]) {
|
public function testMultisiteIntegration($opts = ['file' => null, 'xml' => false, 'multisite' => true, 'skip-deps' => false]) {
|
||||||
return $this->runTestsInContainer(array_merge($opts, ['test_type' => 'integration']));
|
return $this->runTestsInContainer(array_merge($opts, ['test_type' => 'integration']));
|
||||||
}
|
|
||||||
|
|
||||||
public function testWooIntegration(array $opts = ['file' => null, 'xml' => false, 'multisite' => false, 'debug' => false, 'enable-cot' => false, 'enable-cot-sync' => false]) {
|
|
||||||
return $this->runTestsInContainer(array_merge($opts, ['test_type' => 'integration', 'group' => 'woo', 'skip-deps' => true, 'skip-plugins' => false]));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testBaseIntegration(array $opts = ['file' => null, 'xml' => false, 'multisite' => false, 'debug' => false]) {
|
|
||||||
return $this->runTestsInContainer(array_merge($opts, ['test_type' => 'integration', 'skip-group' => 'woo', 'skip-deps' => true, 'skip-plugins' => true]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCoverage($opts = ['file' => null, 'xml' => false]) {
|
public function testCoverage($opts = ['file' => null, 'xml' => false]) {
|
||||||
@ -259,32 +252,20 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
return $this->testIntegration($opts);
|
return $this->testIntegration($opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAcceptance($opts = ['file' => null, 'skip-deps' => false, 'group' => null, 'timeout' => null, 'enable-cot' => false, 'enable-cot-sync' => false]) {
|
public function testAcceptance($opts = ['file' => null, 'skip-deps' => false, 'timeout' => null]) {
|
||||||
return $this->runTestsInContainer($opts);
|
return $this->runTestsInContainer($opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAcceptanceMultisite($opts = ['file' => null, 'skip-deps' => false, 'group' => null, 'timeout' => null, 'enable-cot' => false, 'enable-cot-sync' => false]) {
|
public function testAcceptanceMultisite($opts = ['file' => null, 'skip-deps' => false, 'timeout' => null]) {
|
||||||
return $this->runTestsInContainer(array_merge($opts, ['multisite' => true]));
|
return $this->runTestsInContainer(array_merge($opts, ['multisite' => true]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes docker stuff related to tests including docker images.
|
|
||||||
*/
|
|
||||||
public function deleteDocker() {
|
public function deleteDocker() {
|
||||||
return $this->taskExec(
|
return $this->taskExec(
|
||||||
'docker-compose down -v --remove-orphans --rmi all'
|
'docker-compose down -v --remove-orphans --rmi all'
|
||||||
)->dir(__DIR__ . '/tests/docker')->run();
|
)->dir(__DIR__ . '/tests/docker')->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes docker containers and volumes used in tests
|
|
||||||
*/
|
|
||||||
public function resetTestDocker() {
|
|
||||||
return $this->taskExec(
|
|
||||||
'docker-compose down -v --remove-orphans'
|
|
||||||
)->dir(__DIR__ . '/tests/docker')->run();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testFailedUnit() {
|
public function testFailedUnit() {
|
||||||
$this->_exec('vendor/bin/codecept build');
|
$this->_exec('vendor/bin/codecept build');
|
||||||
return $this->_exec('vendor/bin/codecept run unit -g failed');
|
return $this->_exec('vendor/bin/codecept run unit -g failed');
|
||||||
@ -434,25 +415,23 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function qaLintJavascript() {
|
public function qaLintJavascript() {
|
||||||
return $this->_exec('pnpm run check-types && pnpm run lint');
|
return $this->_exec('npm run check-types && npm run lint');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function qaLintCss() {
|
public function qaLintCss() {
|
||||||
return $this->_exec('pnpm run stylelint-check -- "assets/css/src/**/*.scss"');
|
return $this->_exec('npm run stylelint-check -- "assets/css/src/**/*.scss"');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function qaCodeSniffer(array $filesToCheck, $opts = ['severity' => 'all']) {
|
public function qaCodeSniffer(array $filesToCheck, $opts = ['severity' => 'all']) {
|
||||||
$severityFlag = $opts['severity'] === 'all' ? '-w' : '-n';
|
$severityFlag = $opts['severity'] === 'all' ? '-w' : '-n';
|
||||||
$task = implode(' ', [
|
$task = implode(' ', [
|
||||||
'php -d memory_limit=-1',
|
|
||||||
'./tasks/code_sniffer/vendor/bin/phpcs',
|
'./tasks/code_sniffer/vendor/bin/phpcs',
|
||||||
'--extensions=php',
|
'--extensions=php',
|
||||||
$severityFlag,
|
$severityFlag,
|
||||||
'--standard=tasks/code_sniffer/MailPoet',
|
'--standard=tasks/code_sniffer/MailPoet',
|
||||||
'-s',
|
'-s',
|
||||||
]);
|
]);
|
||||||
|
$foldersToIgnore = [
|
||||||
$ignorePaths = [
|
|
||||||
'.mp_svn',
|
'.mp_svn',
|
||||||
'assets',
|
'assets',
|
||||||
'doc',
|
'doc',
|
||||||
@ -475,17 +454,11 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
'vendor-prefixed',
|
'vendor-prefixed',
|
||||||
'views',
|
'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) : '.';
|
$stringFilesToCheck = !empty($filesToCheck) ? implode(' ', $filesToCheck) : '.';
|
||||||
|
|
||||||
return $this
|
return $this
|
||||||
->taskExec($task)
|
->taskExec($task)
|
||||||
->arg('--ignore=' . implode(',', $ignorePatterns))
|
->arg('--ignore=' . implode(',', $foldersToIgnore))
|
||||||
->rawArg($stringFilesToCheck)
|
->rawArg($stringFilesToCheck)
|
||||||
->run();
|
->run();
|
||||||
}
|
}
|
||||||
@ -581,11 +554,11 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function storybookBuild() {
|
public function storybookBuild() {
|
||||||
return $this->_exec('pnpm run build-storybook');
|
return $this->_exec('npm run build-storybook');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function storybookWatch() {
|
public function storybookWatch() {
|
||||||
return $this->_exec('pnpm run storybook');
|
return $this->_exec('npm run storybook');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function svnCheckout() {
|
public function svnCheckout() {
|
||||||
@ -923,41 +896,6 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
$printReviewers($logins, 'Full');
|
$printReviewers($logins, 'Full');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function displayCreatedPullRequests(ConsoleIO $io, int $months = 6) {
|
|
||||||
$projects = [
|
|
||||||
\MailPoetTasks\Release\GitHubController::PROJECT_SHOP,
|
|
||||||
\MailPoetTasks\Release\GitHubController::PROJECT_MAILPOET,
|
|
||||||
\MailPoetTasks\Release\GitHubController::PROJECT_PREMIUM,
|
|
||||||
];
|
|
||||||
$io->progressStart(count($projects));
|
|
||||||
$counts = [];
|
|
||||||
foreach ($projects as $project) {
|
|
||||||
$githubController = $this->createGitHubController($project);
|
|
||||||
$countsProject = $githubController->calculatePRcounts($months);
|
|
||||||
|
|
||||||
foreach ($countsProject as $login => $num) {
|
|
||||||
if (!isset($counts[$login])) {
|
|
||||||
$counts[$login] = 0;
|
|
||||||
}
|
|
||||||
$counts[$login] += $num;
|
|
||||||
}
|
|
||||||
$io->progressAdvance();
|
|
||||||
}
|
|
||||||
$io->progressFinish();
|
|
||||||
|
|
||||||
arsort($counts);
|
|
||||||
$io->title('Pull Request counts');
|
|
||||||
$outputList = [];
|
|
||||||
foreach ($counts as $login => $num) {
|
|
||||||
$outputList[] = [
|
|
||||||
$login,
|
|
||||||
$num,
|
|
||||||
round($num / $months, 2),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
$io->table(['Login', 'Count', 'Per month'], $outputList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function releaseCheckPullRequest($version) {
|
public function releaseCheckPullRequest($version) {
|
||||||
$this->createGitHubController()
|
$this->createGitHubController()
|
||||||
->checkReleasePullRequestPassed($version);
|
->checkReleasePullRequestPassed($version);
|
||||||
@ -1087,20 +1025,10 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function downloadWooCommerceZip($tag = null) {
|
public function downloadWooCommerceZip($tag = null) {
|
||||||
if ($tag === 'woo-cot-beta') {
|
|
||||||
$this->downloadWooCommerceCotZip();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$this->createWpOrgDownloader('woocommerce')
|
$this->createWpOrgDownloader('woocommerce')
|
||||||
->downloadPluginZip('woocommerce.zip', __DIR__ . '/tests/plugins/', $tag);
|
->downloadPluginZip('woocommerce.zip', __DIR__ . '/tests/plugins/', $tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function downloadWooCommerceCotZip() {
|
|
||||||
$cotBuildUrl = 'https://github.com/woocommerce/woocommerce/files/9706609/woocommerce.zip';
|
|
||||||
file_put_contents(__DIR__ . '/tests/plugins/woocommerce.zip', file_get_contents($cotBuildUrl));
|
|
||||||
file_put_contents(__DIR__ . '/tests/plugins/woocommerce.zip-info', $cotBuildUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function generateData($generatorName = null, $threads = 1) {
|
public function generateData($generatorName = null, $threads = 1) {
|
||||||
require_once __DIR__ . '/tests/DataGenerator/_bootstrap.php';
|
require_once __DIR__ . '/tests/DataGenerator/_bootstrap.php';
|
||||||
$generator = new \MailPoet\Test\DataGenerator\DataGenerator(new \Codeception\Lib\Console\Output([]));
|
$generator = new \MailPoet\Test\DataGenerator\DataGenerator(new \Codeception\Lib\Console\Output([]));
|
||||||
@ -1278,18 +1206,14 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
private function runTestsInContainer(array $opts) {
|
private function runTestsInContainer(array $opts) {
|
||||||
$testType = $opts['test_type'] ?? 'acceptance';
|
$testType = $opts['test_type'] ?? 'acceptance';
|
||||||
$this->doctrineGenerateCache();
|
$this->doctrineGenerateCache();
|
||||||
|
|
||||||
return $this->taskExec(
|
return $this->taskExec(
|
||||||
'COMPOSE_HTTP_TIMEOUT=200 docker-compose run ' .
|
'COMPOSE_HTTP_TIMEOUT=200 docker-compose run ' .
|
||||||
(isset($opts['skip-deps']) && $opts['skip-deps'] ? '-e SKIP_DEPS=1 ' : '') .
|
(isset($opts['skip-deps']) && $opts['skip-deps'] ? '-e SKIP_DEPS=1 ' : '') .
|
||||||
(isset($opts['enable-cot']) && $opts['enable-cot'] ? '-e ENABLE_COT=1 ' : '') .
|
|
||||||
(isset($opts['enable-cot-sync']) && $opts['enable-cot-sync'] ? '-e ENABLE_COT_SYNC=1 ' : '') .
|
|
||||||
(isset($opts['skip-plugins']) && $opts['skip-plugins'] ? '-e SKIP_PLUGINS=1 ' : '') .
|
|
||||||
(isset($opts['timeout']) && $opts['timeout'] ? '-e WAIT_TIMEOUT=' . (int)$opts['timeout'] . ' ' : '') .
|
(isset($opts['timeout']) && $opts['timeout'] ? '-e WAIT_TIMEOUT=' . (int)$opts['timeout'] . ' ' : '') .
|
||||||
(isset($opts['multisite']) && $opts['multisite'] ? '-e MULTISITE=1 ' : '-e MULTISITE=0 ') .
|
(isset($opts['multisite']) && $opts['multisite'] ? '-e MULTISITE=1 ' : '-e MULTISITE=0 ') .
|
||||||
"codeception_{$testType} --steps --debug -vvv " .
|
"codeception_{$testType} --steps --debug -vvv " .
|
||||||
(isset($opts['xml']) && $opts['xml'] ? '--xml ' : '') .
|
(isset($opts['xml']) && $opts['xml'] ? '--xml ' : '') .
|
||||||
(isset($opts['group']) && $opts['group'] ? '--group ' . $opts['group'] . ' ' : '') .
|
|
||||||
(isset($opts['skip-group']) && $opts['skip-group'] ? '--skip-group ' . $opts['skip-group'] . ' ' : '') .
|
|
||||||
'-f ' . (isset($opts['file']) && $opts['file'] ? $opts['file'] : '')
|
'-f ' . (isset($opts['file']) && $opts['file'] ? $opts['file'] : '')
|
||||||
)->dir(__DIR__ . '/tests/docker')->run();
|
)->dir(__DIR__ . '/tests/docker')->run();
|
||||||
}
|
}
|
||||||
|
14
mailpoet/assets/css/src/components-admin/_menu.scss
Normal file
14
mailpoet/assets/css/src/components-admin/_menu.scss
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: 'mailpoet-icon';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
src: url('data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAAYcAAsAAAAABdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAABCAAAAGAAAABgDxIFHGNtYXAAAAFoAAAAVAAAAFQXVtKHZ2FzcAAAAbwAAAAIAAAACAAAABBnbHlmAAABxAAAAhQAAAIU239UpGhlYWQAAAPYAAAANgAAADYYSCB9aGhlYQAABBAAAAAkAAAAJAelA8ZobXR4AAAENAAAABQAAAAUCeMAAGxvY2EAAARIAAAADAAAAAwAKAEebWF4cAAABFQAAAAgAAAAIAAIAMJuYW1lAAAEdAAAAYYAAAGGmUoJ+3Bvc3QAAAX8AAAAIAAAACAAAwAAAAMC8gGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAA6QADwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADgAAAAKAAgAAgACAAEAIOkA//3//wAAAAAAIOkA//3//wAB/+MXBAADAAEAAAAAAAAAAAAAAAEAAf//AA8AAQAAAAAAAAAAAAIAADc5AQAAAAABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAgAA/8AD4wPAAGQAvwAAEzI2Nz4BNTQwOQEREx4BFzEeATM4ATMyNjcjPgE3MRMRHAExFBYXMR4BMzI2Nz4BNTA0OQERPAE1NCYnMS4BIyoBIyIGBzMOAQcVCwEuASc1LgEjKgEjIgYHMw4BFREUFhceATMFJy4BIyIGBzEOASsBOAExIgYHMQcnLgErAS4BJxcuASMiBgcxBw4BFTEcATEUFhcxHgEXMTM4ATEyFhcdARQWMzI2PQE+ATM4ATEzPgE3Iz4BNTwBOQEuASc19xEYBgYHbwQNCAgXEAEKEwkBCg0DdggGBxcPEhcHBgcMCgodEQEDAg8dDQEMEQSBhgQPCgscEwEDAQ8bDAELDAcGBxcQAtkQBg8JCRAHECoYjDJZIQcHIVkyjRgpEQEHEAkJDwYQCAoICCBSL40sRAwUJCMUDEQsjS9TIAEICAEKCAF5BwgHEQoBASv+2QsRBwcGBAUFEQoBSP6+AQILEwcHCAgHBxIKAQHdAQEBDBYGBwcHBggWDgH+gwGADRQHAQcHBwcHGBD+LA4UBwYHtAwFBQYGDhAmIQgHISYBEA4BBgcGBQwGEwsBAQsSBh0hATUoAQEEGRkEASk1ASEdBhMKAQELEwYBAAEAAAAAAACzy1ndXw889QALBAAAAAAA2qNuAAAAAADao24AAAD/wAPjA8AAAAAIAAIAAAAAAAAAAQAAA8D/wAAABAAAAAAAA+MAAQAAAAAAAAAAAAAAAAAAAAUEAAAAAAAAAAAAAAACAAAAA+MAAAAAAAAACgAUAB4BCgABAAAABQDAAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAADgCuAAEAAAAAAAEABwAAAAEAAAAAAAIABwBgAAEAAAAAAAMABwA2AAEAAAAAAAQABwB1AAEAAAAAAAUACwAVAAEAAAAAAAYABwBLAAEAAAAAAAoAGgCKAAMAAQQJAAEADgAHAAMAAQQJAAIADgBnAAMAAQQJAAMADgA9AAMAAQQJAAQADgB8AAMAAQQJAAUAFgAgAAMAAQQJAAYADgBSAAMAAQQJAAoANACkaWNvbW9vbgBpAGMAbwBtAG8AbwBuVmVyc2lvbiAxLjAAVgBlAHIAcwBpAG8AbgAgADEALgAwaWNvbW9vbgBpAGMAbwBtAG8AbwBuaWNvbW9vbgBpAGMAbwBtAG8AbwBuUmVndWxhcgBSAGUAZwB1AGwAYQByaWNvbW9vbgBpAGMAbwBtAG8AbwBuRm9udCBnZW5lcmF0ZWQgYnkgSWNvTW9vbi4ARgBvAG4AdAAgAGcAZQBuAGUAcgBhAHQAZQBkACAAYgB5ACAASQBjAG8ATQBvAG8AbgAuAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==') format('woff');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* menu icon */
|
||||||
|
#adminmenu #toplevel_page_mailpoet-newsletters .wp-menu-image:before {
|
||||||
|
content: '\e900';
|
||||||
|
font-family: 'mailpoet-icon';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
@ -4,7 +4,6 @@
|
|||||||
border: none;
|
border: none;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
box-shadow: 0 0 0 4px #fbfbfb;
|
box-shadow: 0 0 0 4px #fbfbfb;
|
||||||
cursor: pointer;
|
|
||||||
fill: #2b3337;
|
fill: #2b3337;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
.mailpoet-automation-workflow-add-trigger {
|
|
||||||
align-items: center;
|
|
||||||
border: 1px dashed #c3c4c7;
|
|
||||||
border-radius: 4px;
|
|
||||||
color: #757575;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
fill: #757575;
|
|
||||||
height: 73px;
|
|
||||||
justify-content: center;
|
|
||||||
margin: 4px auto;
|
|
||||||
padding: 20px 32px;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
box-shadow:
|
|
||||||
0 0 0 1px #fbfbfb, // space
|
|
||||||
0 0 0 calc(var(--wp-admin-border-width-focus) + 1px) var(--wp-admin-theme-color), // focus ring
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
// See: https://github.com/WordPress/gutenberg/blob/af7da80dd54d7fe52772890e2cc1b65073db9655/packages/block-editor/src/components/block-icon/style.scss
|
|
||||||
|
|
||||||
.block-editor-block-icon {
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
height: 24px;
|
|
||||||
justify-content: center;
|
|
||||||
width: 24px;
|
|
||||||
|
|
||||||
&.has-colors {
|
|
||||||
svg {
|
|
||||||
fill: currentColor;
|
|
||||||
|
|
||||||
// Optimize for high contrast modes.
|
|
||||||
// See also https://blogs.windows.com/msedgedev/2020/09/17/styling-for-windows-high-contrast-with-new-standards-for-forced-colors/.
|
|
||||||
|
|
||||||
@media (forced-colors: active) {
|
|
||||||
fill: CanvasText;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Icons with width/height attributes below 20px will be sized up to 20px,
|
|
||||||
// and icons with width/height attributes above 24px will be sized down to
|
|
||||||
// 24px. Icons with width/height >=20px and <=24px will display at the
|
|
||||||
// indicated size.
|
|
||||||
// See: https://github.com/WordPress/gutenberg/pull/9828
|
|
||||||
svg {
|
|
||||||
max-height: 24px;
|
|
||||||
max-width: 24px;
|
|
||||||
min-height: 20px;
|
|
||||||
min-width: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
.mailpoet-automation-chip {
|
|
||||||
align-items: center;
|
|
||||||
background: #fcf0f1;
|
|
||||||
border-radius: 9999px;
|
|
||||||
color: #8a2424;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
font-size: 13px;
|
|
||||||
height: 20px;
|
|
||||||
padding: 0 8px;
|
|
||||||
|
|
||||||
&.chip-small {
|
|
||||||
font-size: 13px;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.chip-medium {
|
|
||||||
font-size: 13px;
|
|
||||||
height: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.chip-large {
|
|
||||||
font-size: 14px;
|
|
||||||
height: 32px;
|
|
||||||
padding: 0 12px;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
.mailpoet-automatoin-deactivate-modal {
|
|
||||||
color: #1d2327;
|
|
||||||
font-size: 13px;
|
|
||||||
line-height: 21px;
|
|
||||||
max-width: 480px;
|
|
||||||
|
|
||||||
.mailpoet-automation-options {
|
|
||||||
li {
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-option {
|
|
||||||
border: 2px solid #dcdcde;
|
|
||||||
border-radius: 4px;
|
|
||||||
color: #646970;
|
|
||||||
display: grid;
|
|
||||||
font-size: 12px;
|
|
||||||
grid-gap: 8px;
|
|
||||||
grid-template-columns: 20px auto;
|
|
||||||
line-height: 16px;
|
|
||||||
padding: 8px;
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
border-color: #2271b1;
|
|
||||||
}
|
|
||||||
|
|
||||||
strong {
|
|
||||||
color: #1d2327;
|
|
||||||
display: block;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: normal;
|
|
||||||
line-height: 21px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.components-button {
|
|
||||||
float: right;
|
|
||||||
|
|
||||||
&.is-tertiary {
|
|
||||||
margin-right: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
.mailpoet-automation-errors {
|
|
||||||
padding: 8px 0;
|
|
||||||
width: 280px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-errors-header {
|
|
||||||
font-weight: 600;
|
|
||||||
padding: 8px 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-step-error {
|
|
||||||
align-items: center;
|
|
||||||
appearance: none;
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
cursor: pointer;
|
|
||||||
display: grid;
|
|
||||||
gap: 12px;
|
|
||||||
grid-template-columns: auto 1fr;
|
|
||||||
padding: 9px 12px;
|
|
||||||
text-align: left;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: #f6f7f7;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus-visible {
|
|
||||||
box-shadow: inset 0 0 0 1.5px #2271b1;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
// See: https://github.com/WordPress/gutenberg/blob/659377eac576ac34f68dc9762187eb2f6aec2151/packages/edit-navigation/src/components/notices/style.scss
|
|
||||||
|
|
||||||
.mailpoet-automation-editor-notices__snackbar-list {
|
|
||||||
bottom: 0;
|
|
||||||
padding: 20px;
|
|
||||||
position: fixed;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-editor-notices__notice-list {
|
|
||||||
// Notices have some unusual margin and padding by default, reset that.
|
|
||||||
.components-notice {
|
|
||||||
border-bottom: 1px solid rgba(0, 0, 0, .2);
|
|
||||||
box-sizing: border-box;
|
|
||||||
margin: 0;
|
|
||||||
min-height: 60px;
|
|
||||||
padding: 0 12px;
|
|
||||||
|
|
||||||
// Make sure the close button is centered.
|
|
||||||
.components-button {
|
|
||||||
align-self: initial;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,138 +0,0 @@
|
|||||||
.mailpoet-automation-sidebar {
|
|
||||||
padding-bottom: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.components-panel__body-title.mailpoet-automation-panel-plain-body-title {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-panel-plain-body-title-text {
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: normal;
|
|
||||||
padding: 16px 48px 16px 16px;
|
|
||||||
|
|
||||||
label & {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-panel-plain-body-title-action {
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
padding: 8px 16px;
|
|
||||||
|
|
||||||
button {
|
|
||||||
height: auto;
|
|
||||||
padding: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-step-name-dropdown {
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-panel-plain-body-title-text {
|
|
||||||
padding-left: 0;
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-panel-plain-body-title-action {
|
|
||||||
margin-top: -10px;
|
|
||||||
padding-right: 0;
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-step-name-popover {
|
|
||||||
margin-top: -25px;
|
|
||||||
padding: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-step-name-input {
|
|
||||||
min-width: 208px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-deactive {
|
|
||||||
color: #757575;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-activate-panel {
|
|
||||||
animation: mailpoet-automation-activate-panel-animation .1s forwards;
|
|
||||||
background: #fff;
|
|
||||||
border-left: 1px solid #ddd;
|
|
||||||
bottom: 0;
|
|
||||||
height: 100%;
|
|
||||||
left: auto;
|
|
||||||
overflow: auto;
|
|
||||||
position: fixed;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
transform: translateX(100%);
|
|
||||||
width: 281px;
|
|
||||||
z-index: 999999;
|
|
||||||
|
|
||||||
button {
|
|
||||||
justify-content: center;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-activate-panel__header {
|
|
||||||
align-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
height: 61px;
|
|
||||||
|
|
||||||
.has-icon {
|
|
||||||
margin-left: auto;
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-activate-panel__header,
|
|
||||||
.mailpoet-automation-activate-panel__section {
|
|
||||||
border-bottom: 1px solid #ddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-activate-panel__header,
|
|
||||||
.mailpoet-automation-activate-panel__body {
|
|
||||||
padding-left: 16px;
|
|
||||||
padding-right: 16px;
|
|
||||||
|
|
||||||
.components-spinner {
|
|
||||||
display: block;
|
|
||||||
margin: 100px auto 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-activate-panel__section {
|
|
||||||
margin-left: -16px;
|
|
||||||
margin-right: -16px;
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-activate-panel__header-activate-button,
|
|
||||||
.mailpoet-automation-activate-panel__header-cancel-button {
|
|
||||||
flex-grow: 1;
|
|
||||||
max-width: 160px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-activate-panel__header-activate-button {
|
|
||||||
padding-right: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-activate-panel__header-cancel-button {
|
|
||||||
padding-left: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes mailpoet-automation-activate-panel-animation {
|
|
||||||
100% {
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,8 +2,9 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
background: #c3c4c7;
|
background: #c3c4c7;
|
||||||
display: grid;
|
display: grid;
|
||||||
height: 64px;
|
height: 100%;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
min-height: 100px;
|
||||||
width: 1px;
|
width: 1px;
|
||||||
}
|
}
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
// See: https://github.com/WordPress/gutenberg/blob/af7da80dd54d7fe52772890e2cc1b65073db9655/packages/block-editor/src/components/block-card/style.scss
|
|
||||||
|
|
||||||
.block-editor-block-card {
|
|
||||||
align-items: flex-start;
|
|
||||||
display: flex;
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.block-editor-block-card__content {
|
|
||||||
flex-grow: 1;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.block-editor-block-card__title {
|
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
&.block-editor-block-card__title {
|
|
||||||
line-height: 24px;
|
|
||||||
margin: 0 0 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.block-editor-block-card__description {
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.block-editor-block-card .block-editor-block-icon {
|
|
||||||
flex: 0 0 24px;
|
|
||||||
height: 24px;
|
|
||||||
margin-left: 0;
|
|
||||||
margin-right: 12px;
|
|
||||||
width: 24px;
|
|
||||||
}
|
|
@ -1,22 +1,3 @@
|
|||||||
.mailpoet-automation-editor-step-wrapper {
|
|
||||||
margin: auto;
|
|
||||||
position: relative;
|
|
||||||
width: 280px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-step-more-menu {
|
|
||||||
position: absolute;
|
|
||||||
right: 4px;
|
|
||||||
top: 14px;
|
|
||||||
|
|
||||||
button.components-button.is-small.has-icon {
|
|
||||||
height: 24px;
|
|
||||||
min-width: 24px;
|
|
||||||
padding: 3px;
|
|
||||||
width: 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-editor-step {
|
.mailpoet-automation-editor-step {
|
||||||
appearance: none;
|
appearance: none;
|
||||||
background: white;
|
background: white;
|
||||||
@ -30,23 +11,14 @@
|
|||||||
margin: 4px auto;
|
margin: 4px auto;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
width: 100%;
|
width: 280px;
|
||||||
|
|
||||||
&.is-unknown-step {
|
&:focus {
|
||||||
background: #f0f0f1;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus,
|
|
||||||
&.is-selected-step {
|
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 0 0 1px #fbfbfb, // space
|
0 0 0 1px #fbfbfb, // space
|
||||||
0 0 0 calc(var(--wp-admin-border-width-focus) + 1px) var(--wp-admin-theme-color), // focus ring
|
0 0 0 calc(var(--wp-admin-border-width-focus) + 1px) var(--wp-admin-theme-color), // focus ring
|
||||||
0 1px 2px rgba(0, 0, 0, .05); // original shadow
|
0 1px 2px rgba(0, 0, 0, .05); // original shadow
|
||||||
}
|
}
|
||||||
|
|
||||||
&:has(.mailpoet-automation-editor-step-footer) {
|
|
||||||
padding-bottom: 8px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mailpoet-automation-editor-step-icon {
|
.mailpoet-automation-editor-step-icon {
|
||||||
@ -59,23 +31,4 @@
|
|||||||
|
|
||||||
.mailpoet-automation-editor-step-subtitle {
|
.mailpoet-automation-editor-step-subtitle {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-editor-step-footer {
|
|
||||||
display: flex;
|
|
||||||
grid-column: 1 / -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-editor-step-error {
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-colored-icon {
|
|
||||||
border-radius: 50%;
|
|
||||||
box-sizing: content-box;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 12px;
|
|
||||||
position: relative;
|
|
||||||
}
|
}
|
||||||
|
@ -7,31 +7,3 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
padding: 50px 20px;
|
padding: 50px 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mailpoet-automation-editor-workflow-end {
|
|
||||||
background: #8c8f94;
|
|
||||||
border-radius: 999999px;
|
|
||||||
fill: white;
|
|
||||||
height: 18px;
|
|
||||||
margin: 4px auto;
|
|
||||||
padding: 3px;
|
|
||||||
width: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-editor-stats {
|
|
||||||
margin: 0 auto 32px;
|
|
||||||
max-width: 480px;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
.mailpoet-automation-stats-item {
|
|
||||||
line-height: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-stats-label {
|
|
||||||
color: #787c82;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-stats-value {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
@import './mailpoet/button';
|
|
||||||
@import './mailpoet/edit';
|
|
||||||
@import './mailpoet/thumbnail';
|
|
@ -1,37 +0,0 @@
|
|||||||
.components-button.mailpoet-automation-button-sidebar-primary,
|
|
||||||
.components-button.mailpoet-automation-button-sidebar-primary.has-text,
|
|
||||||
.components-button.mailpoet-automation-button-sidebar-primary.has-icon {
|
|
||||||
background: #1d2327;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
&:hover:not(:disabled) {
|
|
||||||
background: #1d2327;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:disabled {
|
|
||||||
color: rgba(255, 255, 255, .4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.is-busy {
|
|
||||||
--background-color-1: #2c3236;
|
|
||||||
--background-color-2: #535659;
|
|
||||||
background-image:
|
|
||||||
linear-gradient(
|
|
||||||
-45deg,
|
|
||||||
var(--background-color-1) 33%,
|
|
||||||
var(--background-color-2) 33%,
|
|
||||||
var(--background-color-2) 70%,
|
|
||||||
var(--background-color-1) 70%
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.components-button.mailpoet-automation-button-centered,
|
|
||||||
.components-button.mailpoet-automation-button-centered.has-text,
|
|
||||||
.components-button.mailpoet-automation-button-centered.has-icon {
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
.mailpoet-automation-email-content-separator {
|
|
||||||
height: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-email-buttons {
|
|
||||||
display: grid;
|
|
||||||
gap: 8px;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
.mailpoet-automation-thumbnail-box {
|
|
||||||
align-items: center;
|
|
||||||
background: #f6f7f7;
|
|
||||||
border: 1px solid #2c3338;
|
|
||||||
display: flex;
|
|
||||||
height: 280px;
|
|
||||||
justify-content: center;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-thumbnail-spinner {
|
|
||||||
height: 32px;
|
|
||||||
width: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-thumbnail-wrapper {
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
justify-content: center;
|
|
||||||
overflow: hidden;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-thumbnail-image {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 192px;
|
|
||||||
}
|
|
@ -1,64 +1,3 @@
|
|||||||
#mailpoet_automation * {
|
#mailpoet_automation * {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
.mailpoet-add-new-button {
|
|
||||||
padding-right: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-listing-heading {
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-listing {
|
|
||||||
box-shadow: none;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-filter-tab-panel {
|
|
||||||
background-color: #fff;
|
|
||||||
border: 1px solid #dcdcde;
|
|
||||||
border-radius: 2px;
|
|
||||||
|
|
||||||
.components-tab-panel__tabs {
|
|
||||||
box-shadow: inset 0 -1px 0 0 #dcdcde;
|
|
||||||
}
|
|
||||||
|
|
||||||
.components-tab-panel__tabs-item:focus {
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.components-tab-panel__tabs-item.is-active {
|
|
||||||
box-shadow: inset 0 -4px 0 0 var(--wp-admin-theme-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.components-tab-panel__tabs-item:focus-visible {
|
|
||||||
box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.components-tab-panel__tabs-item.is-active:focus-visible {
|
|
||||||
box-shadow:
|
|
||||||
inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color),
|
|
||||||
inset 0 -4px 0 0 var(--wp-admin-theme-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.count {
|
|
||||||
background-color: #f0f0f1;
|
|
||||||
border-radius: 12px;
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: 400;
|
|
||||||
margin-left: 6px;
|
|
||||||
padding: 2px 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-listing-more-button button.components-button {
|
|
||||||
height: 36px;
|
|
||||||
padding: 0;
|
|
||||||
width: 36px;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
height: 28px;
|
|
||||||
width: 28px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
.mailpoet-automation-listing-cell-actions {
|
|
||||||
align-items: center;
|
|
||||||
display: grid;
|
|
||||||
gap: 8px;
|
|
||||||
grid-auto-flow: column;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
@ -1,8 +1,6 @@
|
|||||||
.mailpoet-automation-listing-cell-status {
|
.mailpoet-automation-listing-cell-status {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: grid;
|
display: flex;
|
||||||
grid-auto-flow: column;
|
|
||||||
white-space: nowrap;
|
|
||||||
|
|
||||||
> div.components-base-control > div.components-base-control__field {
|
> div.components-base-control > div.components-base-control__field {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
.mailpoet-automation-stats {
|
|
||||||
display: grid;
|
|
||||||
grid-auto-flow: column;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-stats-item {
|
|
||||||
color: $color-wordpress-heading;
|
|
||||||
display: grid;
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 16px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-stats-label {
|
|
||||||
color: #646970;
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
&.display-after {
|
|
||||||
order: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-stats-value {
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-stats-item-separator {
|
|
||||||
color: #a7aaad;
|
|
||||||
font-size: 20px;
|
|
||||||
margin: 0 16px;
|
|
||||||
}
|
|
@ -83,14 +83,13 @@ h2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjustments for family-font-select in popover
|
|
||||||
.mailpoet_toolbar_item {
|
.mailpoet_toolbar_item {
|
||||||
.mailpoet-font-family-select {
|
align-items: center;
|
||||||
height: 48px;
|
background-color: white;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
.components-input-control__container .components-custom-select-control__button {
|
.mailpoet-font-family-select {
|
||||||
width: 200px;
|
width: $grid-column-small;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force rendering of select arrow on the right
|
// Force rendering of select arrow on the right
|
||||||
|
@ -22,31 +22,18 @@
|
|||||||
min-width: 5em;
|
min-width: 5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.block-editor-panel-color-gradient-settings {
|
|
||||||
border: none;
|
|
||||||
padding: 10px 0;
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.mailpoet-font-family-select {
|
.mailpoet-font-family-select {
|
||||||
.components-flex {
|
button {
|
||||||
height: auto;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.components-input-control__container {
|
.components-custom-select-control__label {
|
||||||
width: 100%;
|
font-weight: bold;
|
||||||
}
|
|
||||||
|
|
||||||
.components-custom-select-control__label {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ p.sender_email_address_warning.sender_email_address_warning a {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p.sender_email_address_warning:first-child {
|
p.sender_email_address_warning:first-child {
|
||||||
margin-top: 0; // unify spacing with parsley errors
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button.mailpoet-button-bigger {
|
.button.mailpoet-button-bigger {
|
||||||
@ -88,37 +88,3 @@ p.sender_email_address_warning:first-child {
|
|||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mailpoet_manage_sender_domain {
|
|
||||||
.mailpoet_table_header {
|
|
||||||
font-weight: 700 !important;
|
|
||||||
text-align: center !important; // to prevent being overwritten by widefat table classes
|
|
||||||
}
|
|
||||||
|
|
||||||
.dns_record_type_column {
|
|
||||||
font-weight: 550 !important;
|
|
||||||
text-align: center !important; // to prevent being overwritten by widefat table classes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body .components-modal__screen-overlay {
|
|
||||||
z-index: 9999999; // increased to overlay Gutenberg block inserter
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-premium-modal.components-modal__frame {
|
|
||||||
max-width: 500px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-premium-modal-footer {
|
|
||||||
display: flex;
|
|
||||||
gap: 12px;
|
|
||||||
justify-content: flex-end;
|
|
||||||
margin-top: 16px;
|
|
||||||
padding-top: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-premium-modal-error {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
margin-top: $grid-gap-half;
|
|
||||||
}
|
|
||||||
|
@ -35,10 +35,6 @@ textarea.regular-text {
|
|||||||
width: 25em !important;
|
width: 25em !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.regular-text-full-width {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include respond-to(small-screen) {
|
@include respond-to(small-screen) {
|
||||||
.select2-container {
|
.select2-container {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
@ -221,18 +217,9 @@ progress::-moz-progress-bar {
|
|||||||
.mailpoet-form-notice-message {
|
.mailpoet-form-notice-message {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
.parsley-errors-list {
|
|
||||||
left: 0;
|
|
||||||
margin-top: 2px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to hide the label because it doesn't fit to our form design, and it's added automatically by Gutenberg component
|
// We need to hide the label because it doesn't fit to our form design, and it's added automatically by Gutenberg component
|
||||||
.mailpoet-form-field-tags label.components-form-token-field__label {
|
.mailpoet-form-field-tags label.components-form-token-field__label {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mailpoet-form-field-disabled {
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
|
@ -92,12 +92,17 @@ h1.title.mailpoet-newsletter-listing-heading {
|
|||||||
margin-bottom: $grid-gap;
|
margin-bottom: $grid-gap;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mailpoet_editor_steps_heading {
|
.mailpoet-newsletter-listing-heading-wrapper {
|
||||||
.mailpoet-top-bar {
|
.mailpoet-top-bar-logo {
|
||||||
left: 0;
|
cursor: pointer;
|
||||||
|
left: 17px;
|
||||||
|
position: absolute;
|
||||||
|
top: 25px;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
.mailpoet-top-bar-beamer {
|
svg {
|
||||||
top: 4px;
|
max-height: 100%;
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
38
mailpoet/assets/css/src/components-plugin/_mp2-migrator.scss
Normal file
38
mailpoet/assets/css/src/components-plugin/_mp2-migrator.scss
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#logger {
|
||||||
|
background-color: transparent;
|
||||||
|
border: 0;
|
||||||
|
border-top: 1px #aba9a9 solid;
|
||||||
|
font-size: .85em;
|
||||||
|
height: 300px;
|
||||||
|
margin-top: 20px;
|
||||||
|
overflow: scroll;
|
||||||
|
padding: 2px;
|
||||||
|
resize: both;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progressbar {
|
||||||
|
background-color: #d8d8d8;
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
$progressbar_color: #fecf23;
|
||||||
|
$progressbar_gradient_to_color: #fd9215;
|
||||||
|
|
||||||
|
.ui-progressbar .ui-progressbar-value {
|
||||||
|
background-color: $progressbar_color;
|
||||||
|
background-image: linear-gradient(to bottom, $progressbar_color, $progressbar_gradient_to_color);
|
||||||
|
border: 0;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: 0 1px 0 rgba(255, 255, 255, .5) inset;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mailpoet_progress_label {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error_msg {
|
||||||
|
color: #f00;
|
||||||
|
}
|
@ -100,12 +100,6 @@ ul.sending-method-benefits {
|
|||||||
.mailpoet-form-input:not(:first-child) {
|
.mailpoet-form-input:not(:first-child) {
|
||||||
margin-top: $grid-gap-half;
|
margin-top: $grid-gap-half;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.mailpoet-import-tags {
|
|
||||||
label.components-form-token-field__label {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mailpoet-settings-inputs-row {
|
.mailpoet-settings-inputs-row {
|
||||||
|
@ -65,18 +65,6 @@ $form-line-height: 1.4;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset fieldset styles in form for backward compatibility. */
|
|
||||||
.mailpoet_paragraph {
|
|
||||||
fieldset,
|
|
||||||
legend {
|
|
||||||
background: transparent;
|
|
||||||
border: 0;
|
|
||||||
color: inherit;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet_textarea {
|
.mailpoet_textarea {
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
@ -11,13 +11,13 @@ select.parsley-error,
|
|||||||
textarea.parsley-error {
|
textarea.parsley-error {
|
||||||
background-color: #f2dede;
|
background-color: #f2dede;
|
||||||
border-color: #eed3d7;
|
border-color: #eed3d7;
|
||||||
color: #900;
|
color: #b94a48;
|
||||||
}
|
}
|
||||||
|
|
||||||
.parsley-errors-list {
|
.parsley-errors-list {
|
||||||
color: #900;
|
color: #b94a48;
|
||||||
font-size: 13px;
|
font-size: .9em;
|
||||||
line-height: 1em;
|
line-height: .9em;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
margin: 8px 0 3px;
|
margin: 8px 0 3px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
@ -38,7 +38,7 @@ textarea.parsley-error {
|
|||||||
|
|
||||||
.parsley-required,
|
.parsley-required,
|
||||||
.parsley-custom-error-message {
|
.parsley-custom-error-message {
|
||||||
color: #900;
|
color: #b94a48;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mailpoet-form-errors {
|
.mailpoet-form-errors {
|
||||||
|
@ -32,7 +32,6 @@ $beamer-dot-size: 8px;
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 2px;
|
top: 2px;
|
||||||
z-index: 1;
|
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
@ -86,8 +85,6 @@ $beamer-dot-size: 8px;
|
|||||||
border: none;
|
border: none;
|
||||||
color: $color-wordpress-grey-dark;
|
color: $color-wordpress-grey-dark;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: 60px;
|
height: 60px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -61,7 +61,7 @@
|
|||||||
margin-top: $grid-gap;
|
margin-top: $grid-gap;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(.mailpoet-full-width) + .mailpoet-form-input:not(.mailpoet-full-width):not(.mailpoet-form-select),
|
&:not(.mailpoet-full-width) + .mailpoet-form-input:not(.mailpoet-full-width),
|
||||||
&:not(.mailpoet-full-width) + .mailpoet-button:not(.mailpoet-full-width) {
|
&:not(.mailpoet-full-width) + .mailpoet-button:not(.mailpoet-full-width) {
|
||||||
margin-left: $grid-gap;
|
margin-left: $grid-gap;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
border: 1px solid $color-input-border !important;
|
border: 1px solid $color-input-border !important;
|
||||||
border-radius: $form-control-border-radius !important;
|
border-radius: $form-control-border-radius !important;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
display: inline-flex;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
min-height: $form-control-height;
|
min-height: $form-control-height;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
@ -10,7 +11,6 @@
|
|||||||
// To align the left padding with the other inputs
|
// To align the left padding with the other inputs
|
||||||
input[type=text].components-form-token-field__input {
|
input[type=text].components-form-token-field__input {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
min-height: 30px;
|
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
}
|
}
|
||||||
// For better fit when the last item is active
|
// For better fit when the last item is active
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// Utilities
|
// Utilities
|
||||||
// Helpers and overrides.
|
// Helpers and overrides.
|
||||||
|
|
||||||
|
@import 'components-admin/menu';
|
||||||
@import 'components-admin/3rd-party-plugins/members';
|
@import 'components-admin/3rd-party-plugins/members';
|
||||||
|
@ -1,30 +1,12 @@
|
|||||||
|
@import '../../../node_modules/@wordpress/components/build-style/style';
|
||||||
@import '../../../node_modules/@wordpress/interface/build-style/style';
|
@import '../../../node_modules/@wordpress/interface/build-style/style';
|
||||||
@import '../../../node_modules/@wordpress/edit-site/build-style/style';
|
@import '../../../node_modules/@wordpress/edit-site/build-style/style';
|
||||||
@import '../../../node_modules/@wordpress/block-editor/build-style/style'; // for inserter styles
|
@import '../../../node_modules/@wordpress/block-editor/build-style/style'; // for inserter styles
|
||||||
@import 'settings/colors';
|
@import 'settings/colors';
|
||||||
|
|
||||||
// automation components
|
|
||||||
|
|
||||||
@import './components-automation/statistics';
|
|
||||||
|
|
||||||
// automation editor
|
|
||||||
|
|
||||||
@import './components-automation-editor/add-step-button';
|
@import './components-automation-editor/add-step-button';
|
||||||
@import './components-automation-editor/add-trigger';
|
|
||||||
@import './components-automation-editor/block-icon';
|
|
||||||
@import './components-automation-editor/chip';
|
|
||||||
@import './components-automation-editor/dropdown';
|
@import './components-automation-editor/dropdown';
|
||||||
@import './components-automation-editor/empty-workflow';
|
@import './components-automation-editor/empty-workflow';
|
||||||
@import './components-automation-editor/errors';
|
|
||||||
@import './components-automation-editor/panel';
|
|
||||||
@import './components-automation-editor/separator';
|
@import './components-automation-editor/separator';
|
||||||
@import './components-automation-editor/status';
|
@import './components-automation-editor/status';
|
||||||
@import './components-automation-editor/step';
|
@import './components-automation-editor/step';
|
||||||
@import './components-automation-editor/step-card';
|
|
||||||
@import './components-automation-editor/workflow';
|
@import './components-automation-editor/workflow';
|
||||||
@import './components-automation-editor/notices';
|
|
||||||
@import './components-automation-editor/deactivate-modal';
|
|
||||||
|
|
||||||
// integrations
|
|
||||||
|
|
||||||
@import './components-automation-integrations/mailpoet';
|
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
.mailpoet-automation-templates-heading {
|
|
||||||
margin: auto;
|
|
||||||
max-width: 982px;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.mailpoet-automation-templates {
|
|
||||||
clear: both;
|
|
||||||
cursor: pointer;
|
|
||||||
display: grid;
|
|
||||||
grid-gap: 32px;
|
|
||||||
grid-template-columns: repeat(auto-fill, 306px);
|
|
||||||
justify-content: center;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 982px;
|
|
||||||
padding: 48px 0;
|
|
||||||
|
|
||||||
button.components-button {
|
|
||||||
background: #fff;
|
|
||||||
border: 1px solid #dcdcde;
|
|
||||||
border-radius: 4px;
|
|
||||||
cursor: pointer;
|
|
||||||
display: block;
|
|
||||||
height: 100%;
|
|
||||||
padding: 24px 24px 26px;
|
|
||||||
text-align: left;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: #fff;
|
|
||||||
border: 1px solid #dcdcde;
|
|
||||||
box-shadow: 0 3px 6px rgba(0, 0, 0, .15);
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
border-color: #2271b1;
|
|
||||||
box-shadow: 0 3px 6px rgba(0, 0, 0, .15);
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
background: transparent;
|
|
||||||
border: none;
|
|
||||||
color: #2271b1;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
line-height: 21px;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin: 8px 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mailpoet-automation-from-scratch {
|
|
||||||
button {
|
|
||||||
align-content: center;
|
|
||||||
border: 2px dashed #dcdcde;
|
|
||||||
display: grid;
|
|
||||||
grid-gap: 24px;
|
|
||||||
justify-items: center;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border: 2px dashed #dcdcde;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
svg {
|
|
||||||
fill: #dcdcde;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +1,6 @@
|
|||||||
@import '../../../node_modules/@woocommerce/components/build-style/style';
|
@import '../../../node_modules/@woocommerce/components/build-style/style';
|
||||||
@import 'settings/colors';
|
@import 'settings/colors';
|
||||||
|
|
||||||
// automation components
|
|
||||||
|
|
||||||
@import './components-automation/statistics';
|
|
||||||
|
|
||||||
// automation listing
|
|
||||||
|
|
||||||
@import './components-automation-listing/listing';
|
@import './components-automation-listing/listing';
|
||||||
@import './components-automation-listing/header';
|
@import './components-automation-listing/header';
|
||||||
@import './components-automation-listing/search';
|
@import './components-automation-listing/search';
|
||||||
@import './components-automation-listing/cells/actions';
|
|
||||||
@import './components-automation-listing/cells/status';
|
@import './components-automation-listing/cells/status';
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
@import 'components-plugin/pages-custom';
|
@import 'components-plugin/pages-custom';
|
||||||
@import 'components-plugin/premium-page';
|
@import 'components-plugin/premium-page';
|
||||||
@import 'components-plugin/menu';
|
@import 'components-plugin/menu';
|
||||||
|
@import 'components-plugin/mp2-migrator';
|
||||||
@import 'components-plugin/newsletter';
|
@import 'components-plugin/newsletter';
|
||||||
@import 'components-plugin/newsletter-templates';
|
@import 'components-plugin/newsletter-templates';
|
||||||
@import 'components-plugin/newsletter-types';
|
@import 'components-plugin/newsletter-types';
|
||||||
|
@ -12,74 +12,3 @@ export function getTrackingData() {
|
|||||||
}
|
}
|
||||||
return trackingDataLoading;
|
return trackingDataLoading;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mapFilterType(filter) {
|
|
||||||
const action = filter.action;
|
|
||||||
const filterType = filter.type;
|
|
||||||
|
|
||||||
// Email
|
|
||||||
if (filterType === 'email') {
|
|
||||||
switch (action) {
|
|
||||||
case 'machineOpensAbsoluteCount':
|
|
||||||
return '# of machine-opens';
|
|
||||||
case 'opensAbsoluteCount':
|
|
||||||
return '# of opens';
|
|
||||||
case 'numberOfOrders':
|
|
||||||
return '# of orders';
|
|
||||||
case 'clicked':
|
|
||||||
return 'clicked';
|
|
||||||
case 'clickedAny':
|
|
||||||
return 'clicked any email';
|
|
||||||
case 'opened':
|
|
||||||
return 'opened';
|
|
||||||
case 'machineOpened':
|
|
||||||
return 'machine-opened';
|
|
||||||
default:
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// User Role
|
|
||||||
if (filterType === 'userRole') {
|
|
||||||
switch (action) {
|
|
||||||
case 'subscriberTag':
|
|
||||||
return 'subscriber tags';
|
|
||||||
case 'subscribedToList':
|
|
||||||
return 'subscribed to list';
|
|
||||||
case 'subscriberScore':
|
|
||||||
return 'score';
|
|
||||||
case 'wordpressRole':
|
|
||||||
return 'WordPress user role';
|
|
||||||
case 'mailpoetCustomField':
|
|
||||||
return 'MailPoet custom field';
|
|
||||||
default:
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// WooCommerce
|
|
||||||
if (filterType === 'woocommerce')
|
|
||||||
switch (action) {
|
|
||||||
case 'customerInCountry':
|
|
||||||
return 'is in country';
|
|
||||||
case 'purchasedCategory':
|
|
||||||
return 'purchased in category';
|
|
||||||
case 'purchasedProduct':
|
|
||||||
return 'purchased product';
|
|
||||||
case 'subscribedDate':
|
|
||||||
return 'subscribed date';
|
|
||||||
case 'totalSpent':
|
|
||||||
return 'total spent';
|
|
||||||
default:
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
// WooCommerce Subscription
|
|
||||||
if (
|
|
||||||
filterType === 'woocommerceSubscription' &&
|
|
||||||
action === 'hasActiveSubscription'
|
|
||||||
)
|
|
||||||
return 'has an active subscription';
|
|
||||||
// WooCommerce Membership
|
|
||||||
if (filterType === 'woocommerceMembership' && action === 'isMemberOf')
|
|
||||||
return 'is active member of';
|
|
||||||
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { api } from '../config';
|
import { api } from './config';
|
||||||
|
|
||||||
const API_URL = `${api.root}/mailpoet/v1/automation`;
|
const API_URL = `${api.root}/mailpoet/v1/automation`;
|
||||||
|
|
@ -1,45 +1,29 @@
|
|||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import { BrowserRouter } from 'react-router-dom';
|
import { Workflow } from './listing/workflow';
|
||||||
import { TopBarWithBeamer } from 'common/top_bar/top_bar';
|
|
||||||
import { plusIcon } from 'common/button/icon/plus';
|
|
||||||
import { Button, Flex, Popover, SlotFillProvider } from '@wordpress/components';
|
|
||||||
import { useSelect } from '@wordpress/data';
|
|
||||||
import { initializeApi, useMutation } from './api';
|
|
||||||
import { createStore, storeName } from './listing/store';
|
|
||||||
import { AutomationListing } from './listing';
|
import { AutomationListing } from './listing';
|
||||||
import { registerApiErrorHandler } from './listing/api-error-handler';
|
|
||||||
import { Notices } from './listing/components/notices';
|
|
||||||
import { WorkflowListingNotices } from './listing/workflow-listing-notices';
|
|
||||||
import { Onboarding } from './onboarding';
|
import { Onboarding } from './onboarding';
|
||||||
import {
|
import {
|
||||||
CreateEmptyWorkflowButton,
|
CreateTestingWorkflowButton,
|
||||||
CreateWorkflowFromTemplateButton,
|
CreateWorkflowFromTemplateButton,
|
||||||
} from './testing';
|
} from './testing';
|
||||||
import { MailPoet } from '../mailpoet';
|
import { useMutation, useQuery } from './api';
|
||||||
|
|
||||||
function Content(): JSX.Element {
|
|
||||||
const count = useSelect((select) => select(storeName).getWorkflowCount());
|
|
||||||
return count > 0 ? <AutomationListing /> : <Onboarding />;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Workflows(): JSX.Element {
|
function Workflows(): JSX.Element {
|
||||||
return (
|
const { data, loading, error } = useQuery<{ data: Workflow[] }>('workflows');
|
||||||
<>
|
|
||||||
<TopBarWithBeamer />
|
if (error) {
|
||||||
<Flex className="mailpoet-automation-listing-heading">
|
return <div>Error: {error}</div>;
|
||||||
<h1 className="wp-heading-inline">Automations</h1>
|
}
|
||||||
<Button
|
|
||||||
href={MailPoet.urls.automationTemplates}
|
if (loading) {
|
||||||
icon={plusIcon}
|
return <div>Loading workflows...</div>;
|
||||||
variant="primary"
|
}
|
||||||
className="mailpoet-add-new-button"
|
|
||||||
>
|
const workflows = data?.data ?? [];
|
||||||
New automation
|
return workflows.length === 0 ? (
|
||||||
</Button>
|
<Onboarding />
|
||||||
</Flex>
|
) : (
|
||||||
<Notices />
|
<AutomationListing workflows={workflows} loading={loading} />
|
||||||
<Content />
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +34,6 @@ function RecreateSchemaButton(): JSX.Element {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<WorkflowListingNotices />
|
|
||||||
<button
|
<button
|
||||||
className="button button-link-delete"
|
className="button button-link-delete"
|
||||||
type="button"
|
type="button"
|
||||||
@ -94,40 +77,26 @@ function DeleteSchemaButton(): JSX.Element {
|
|||||||
|
|
||||||
function App(): JSX.Element {
|
function App(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<SlotFillProvider>
|
<div>
|
||||||
<BrowserRouter>
|
<Workflows />
|
||||||
<div>
|
<div style={{ marginTop: 30, display: 'grid', gridGap: 8 }}>
|
||||||
<Workflows />
|
<CreateTestingWorkflowButton />
|
||||||
<div style={{ marginTop: 30, display: 'grid', gridGap: 8 }}>
|
<CreateWorkflowFromTemplateButton template="delayed-email-after-signup">
|
||||||
<CreateEmptyWorkflowButton />
|
Create testing workflow from template (welcome email)
|
||||||
<CreateWorkflowFromTemplateButton slug="simple-welcome-email">
|
</CreateWorkflowFromTemplateButton>
|
||||||
Create testing workflow from template (welcome email)
|
<CreateWorkflowFromTemplateButton template="welcome-email-sequence">
|
||||||
</CreateWorkflowFromTemplateButton>
|
Create testing workflow from template (welcome sequence)
|
||||||
<CreateWorkflowFromTemplateButton slug="welcome-email-sequence">
|
</CreateWorkflowFromTemplateButton>
|
||||||
Create testing workflow from template (welcome sequence, only
|
<RecreateSchemaButton />
|
||||||
premium)
|
<DeleteSchemaButton />
|
||||||
</CreateWorkflowFromTemplateButton>
|
</div>
|
||||||
<CreateWorkflowFromTemplateButton slug="advanced-welcome-email-sequence">
|
</div>
|
||||||
Create testing workflow from template (advanced welcome sequence,
|
|
||||||
only premium)
|
|
||||||
</CreateWorkflowFromTemplateButton>
|
|
||||||
<RecreateSchemaButton />
|
|
||||||
<DeleteSchemaButton />
|
|
||||||
</div>
|
|
||||||
<Popover.Slot />
|
|
||||||
</div>
|
|
||||||
</BrowserRouter>
|
|
||||||
</SlotFillProvider>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('DOMContentLoaded', () => {
|
window.addEventListener('DOMContentLoaded', () => {
|
||||||
createStore();
|
|
||||||
|
|
||||||
const root = document.getElementById('mailpoet_automation');
|
const root = document.getElementById('mailpoet_automation');
|
||||||
if (root) {
|
if (root) {
|
||||||
registerApiErrorHandler();
|
|
||||||
initializeApi();
|
|
||||||
ReactDOM.render(<App />, root);
|
ReactDOM.render(<App />, root);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
import { Fragment } from '@wordpress/element';
|
|
||||||
|
|
||||||
type Item = {
|
|
||||||
key: string;
|
|
||||||
label: string;
|
|
||||||
value: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
items: Item[];
|
|
||||||
labelPosition?: 'before' | 'after';
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Statistics({
|
|
||||||
items,
|
|
||||||
labelPosition = 'before',
|
|
||||||
}: Props): JSX.Element {
|
|
||||||
const intl = new Intl.NumberFormat();
|
|
||||||
return (
|
|
||||||
<div className="mailpoet-automation-stats">
|
|
||||||
{items.map((item, i) => (
|
|
||||||
<Fragment key={item.key}>
|
|
||||||
<div key={item.key} className="mailpoet-automation-stats-item">
|
|
||||||
<span
|
|
||||||
className={`mailpoet-automation-stats-label display-${labelPosition}`}
|
|
||||||
>
|
|
||||||
{item.label}
|
|
||||||
</span>
|
|
||||||
<span className="mailpoet-automation-stats-value">
|
|
||||||
{intl.format(item.value)}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{i < items.length - 1 && (
|
|
||||||
<div className="mailpoet-automation-stats-item-separator">›</div>
|
|
||||||
)}
|
|
||||||
</Fragment>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
@ -4,9 +4,7 @@ declare global {
|
|||||||
root: string;
|
root: string;
|
||||||
nonce: string;
|
nonce: string;
|
||||||
};
|
};
|
||||||
mailpoet_workflow_count: number;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const api = window.mailpoet_automation_api;
|
export const api = window.mailpoet_automation_api;
|
||||||
export const workflowCount = window.mailpoet_workflow_count;
|
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
import apiFetch, { APIFetchOptions } from '@wordpress/api-fetch';
|
|
||||||
import { dispatch, StoreDescriptor } from '@wordpress/data';
|
|
||||||
import { __ } from '@wordpress/i18n';
|
|
||||||
import { store as noticesStore } from '@wordpress/notices';
|
|
||||||
import { storeName } from './store';
|
|
||||||
import { ApiError } from '../api';
|
|
||||||
|
|
||||||
export const registerApiErrorHandler = (): void =>
|
|
||||||
apiFetch.use(
|
|
||||||
async (
|
|
||||||
options: APIFetchOptions,
|
|
||||||
next: (nextOptions: APIFetchOptions) => Promise<unknown>,
|
|
||||||
) => {
|
|
||||||
try {
|
|
||||||
const result = await next(options);
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
const errorObject = error as ApiError;
|
|
||||||
const status = errorObject.data?.status;
|
|
||||||
const code = errorObject.code;
|
|
||||||
|
|
||||||
if (code === 'mailpoet_automation_workflow_not_valid') {
|
|
||||||
dispatch(storeName).setErrors({ steps: errorObject.data.errors });
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status && status >= 400 && status < 500) {
|
|
||||||
const message = errorObject.message;
|
|
||||||
void dispatch(noticesStore as StoreDescriptor).createErrorNotice(
|
|
||||||
message ?? __('An unknown error occurred.', 'mailpoet'),
|
|
||||||
{ explicitDismiss: true },
|
|
||||||
);
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dispatch(noticesStore as StoreDescriptor).createErrorNotice(
|
|
||||||
__('An unknown error occurred.', 'mailpoet'),
|
|
||||||
{ explicitDismiss: true },
|
|
||||||
);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
@ -1,45 +0,0 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
import {
|
|
||||||
__experimentalConfirmDialog as ConfirmDialog,
|
|
||||||
Button,
|
|
||||||
} from '@wordpress/components';
|
|
||||||
import { useDispatch, useSelect } from '@wordpress/data';
|
|
||||||
import { storeName } from '../../store';
|
|
||||||
|
|
||||||
export function TrashButton(): JSX.Element {
|
|
||||||
const [showConfirmDialog, setShowConfirmDialog] = useState(false);
|
|
||||||
const { workflow } = useSelect(
|
|
||||||
(select) => ({
|
|
||||||
workflow: select(storeName).getWorkflowData(),
|
|
||||||
}),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
const { trash } = useDispatch(storeName);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<ConfirmDialog
|
|
||||||
isOpen={showConfirmDialog}
|
|
||||||
title="Delete workflow"
|
|
||||||
confirmButtonText="Yes, delete"
|
|
||||||
onConfirm={async () => {
|
|
||||||
trash(() => {
|
|
||||||
setShowConfirmDialog(false);
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
onCancel={() => setShowConfirmDialog(false)}
|
|
||||||
__experimentalHideHeader={false}
|
|
||||||
>
|
|
||||||
You are about to delete the “{workflow.name}” workflow.
|
|
||||||
</ConfirmDialog>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
variant="secondary"
|
|
||||||
isDestructive
|
|
||||||
onClick={() => setShowConfirmDialog(true)}
|
|
||||||
>
|
|
||||||
Move to Trash
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
import { ReactNode } from 'react';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
size?: 'small' | 'medium' | 'large';
|
|
||||||
children?: ReactNode;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Chip({ size = 'medium', children }: Props): JSX.Element {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={classNames({
|
|
||||||
'mailpoet-automation-chip': true,
|
|
||||||
'chip-small': size === 'small',
|
|
||||||
'chip-medium': size === 'medium',
|
|
||||||
'chip-large': size === 'large',
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
@ -9,7 +9,7 @@ import { useSelect } from '@wordpress/data';
|
|||||||
import { useRef } from '@wordpress/element';
|
import { useRef } from '@wordpress/element';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { chevronDown } from '@wordpress/icons';
|
import { chevronDown } from '@wordpress/icons';
|
||||||
import { storeName } from '../../store';
|
import { store } from '../../store';
|
||||||
import { WorkflowStatus } from '../../../listing/workflow';
|
import { WorkflowStatus } from '../../../listing/workflow';
|
||||||
|
|
||||||
// See: https://github.com/WordPress/gutenberg/blob/eff0cab2b3181c004dbd15398e570ecec28a3726/packages/edit-site/src/components/header/document-actions/index.js
|
// See: https://github.com/WordPress/gutenberg/blob/eff0cab2b3181c004dbd15398e570ecec28a3726/packages/edit-site/src/components/header/document-actions/index.js
|
||||||
@ -24,9 +24,9 @@ const Dropdown: ComponentType<
|
|||||||
export function DocumentActions({ children }): JSX.Element {
|
export function DocumentActions({ children }): JSX.Element {
|
||||||
const { workflowName, workflowStatus, showIconLabels } = useSelect(
|
const { workflowName, workflowStatus, showIconLabels } = useSelect(
|
||||||
(select) => ({
|
(select) => ({
|
||||||
workflowName: select(storeName).getWorkflowData().name,
|
workflowName: select(store).getWorkflowData().name,
|
||||||
workflowStatus: select(storeName).getWorkflowData().status,
|
workflowStatus: select(store).getWorkflowData().status,
|
||||||
showIconLabels: select(storeName).isFeatureActive('showIconLabels'),
|
showIconLabels: select(store).isFeatureActive('showIconLabels'),
|
||||||
}),
|
}),
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
@ -1,169 +0,0 @@
|
|||||||
import { ComponentType, useContext, useEffect, useMemo, useState } from 'react';
|
|
||||||
import {
|
|
||||||
__unstableComposite as Composite,
|
|
||||||
__unstableCompositeItem as CompositeItem,
|
|
||||||
__unstableUseCompositeState as useCompositeState,
|
|
||||||
Button,
|
|
||||||
Popover as WpPopover,
|
|
||||||
} from '@wordpress/components';
|
|
||||||
import { useDispatch, useSelect } from '@wordpress/data';
|
|
||||||
import { createContext } from '@wordpress/element';
|
|
||||||
import { __ } from '@wordpress/i18n';
|
|
||||||
import { Chip } from '../chip';
|
|
||||||
import { ColoredIcon } from '../icons';
|
|
||||||
import {
|
|
||||||
StepError as StepErrorType,
|
|
||||||
stepSidebarKey,
|
|
||||||
storeName,
|
|
||||||
} from '../../store';
|
|
||||||
|
|
||||||
// properties "offset" and "placement" are missing in WpPopover type definition
|
|
||||||
const Popover: ComponentType<
|
|
||||||
WpPopover.Props & {
|
|
||||||
offset?: number;
|
|
||||||
placement?: string;
|
|
||||||
}
|
|
||||||
> = WpPopover;
|
|
||||||
|
|
||||||
export const ErrorsCompositeContext =
|
|
||||||
createContext<ReturnType<typeof useCompositeState>>(undefined);
|
|
||||||
|
|
||||||
type StepErrorProps = {
|
|
||||||
stepId: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
function StepError({ stepId }: StepErrorProps): JSX.Element {
|
|
||||||
const compositeState = useContext(ErrorsCompositeContext);
|
|
||||||
|
|
||||||
const { steps, workflowData } = useSelect(
|
|
||||||
(select) => ({
|
|
||||||
steps: select(storeName).getSteps(),
|
|
||||||
workflowData: select(storeName).getWorkflowData(),
|
|
||||||
}),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const { openSidebar, selectStep } = useDispatch(storeName);
|
|
||||||
|
|
||||||
const stepData = workflowData.steps[stepId];
|
|
||||||
const step = steps.find(({ key }) => key === stepData.key);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<CompositeItem
|
|
||||||
className="mailpoet-automation-step-error"
|
|
||||||
role="listitem"
|
|
||||||
state={compositeState}
|
|
||||||
onClick={() => {
|
|
||||||
openSidebar(stepSidebarKey);
|
|
||||||
selectStep(stepData);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ColoredIcon
|
|
||||||
icon={step.icon}
|
|
||||||
foreground={step.foreground}
|
|
||||||
background={step.background}
|
|
||||||
width="23px"
|
|
||||||
height="23px"
|
|
||||||
/>
|
|
||||||
{step.title}
|
|
||||||
</CompositeItem>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function Errors(): JSX.Element | null {
|
|
||||||
const [showPopover, setShowPopover] = useState(false);
|
|
||||||
|
|
||||||
const compositeState = useCompositeState({
|
|
||||||
orientation: 'vertical',
|
|
||||||
shift: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { errors, workflowData } = useSelect(
|
|
||||||
(select) => ({
|
|
||||||
errors: select(storeName).getErrors(),
|
|
||||||
workflowData: select(storeName).getWorkflowData(),
|
|
||||||
}),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
// walk the steps tree (breadth first) to produce stable error order
|
|
||||||
const stepErrors = useMemo(() => {
|
|
||||||
if (!errors) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const visited = new Map<string, StepErrorType | undefined>();
|
|
||||||
const ids = workflowData.steps.root.next_steps.map(({ id }) => id);
|
|
||||||
while (ids.length > 0) {
|
|
||||||
const id = ids.shift();
|
|
||||||
if (!visited.has(id)) {
|
|
||||||
visited.set(id, errors.steps[id]);
|
|
||||||
workflowData.steps[id]?.next_steps?.forEach((step) =>
|
|
||||||
ids.push(step.id),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return [...visited.values()].filter((error) => !!error);
|
|
||||||
}, [errors, workflowData]);
|
|
||||||
|
|
||||||
// automatically open the popover when errors appear
|
|
||||||
const hasErrors = stepErrors.length > 0;
|
|
||||||
useEffect(() => {
|
|
||||||
if (hasErrors) {
|
|
||||||
setShowPopover(true);
|
|
||||||
}
|
|
||||||
}, [hasErrors]);
|
|
||||||
|
|
||||||
if (stepErrors.length === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Button
|
|
||||||
variant="link"
|
|
||||||
onClick={() =>
|
|
||||||
setShowPopover((prevState) =>
|
|
||||||
prevState === undefined ? false : !prevState,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onMouseDown={() =>
|
|
||||||
// Catch and mark a mouse down event from an open popover with "undefined" to avoid closing it
|
|
||||||
// (automatically via click outside) and reopening it right after (via the onClick handler).
|
|
||||||
// The "onClose" method of the popover doesn't pass any events so we can't filter them.
|
|
||||||
setShowPopover((prevState) => (prevState ? undefined : prevState))
|
|
||||||
}
|
|
||||||
style={{ textDecoration: 'none', borderRadius: 99999 }}
|
|
||||||
>
|
|
||||||
<Chip>{stepErrors.length} issues</Chip>
|
|
||||||
</Button>
|
|
||||||
{showPopover && (
|
|
||||||
<Popover
|
|
||||||
offset={10}
|
|
||||||
placement="bottom-end"
|
|
||||||
onClose={() =>
|
|
||||||
setShowPopover((prevState) =>
|
|
||||||
prevState === undefined ? undefined : false,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<ErrorsCompositeContext.Provider value={compositeState}>
|
|
||||||
<Composite
|
|
||||||
state={compositeState}
|
|
||||||
role="list"
|
|
||||||
aria-label={__('Workflow errors', 'mailpoet')}
|
|
||||||
className="mailpoet-automation-errors"
|
|
||||||
>
|
|
||||||
<div className="mailpoet-automation-errors-header">
|
|
||||||
{__('The following steps are not fully set:', 'mailpoet')}
|
|
||||||
</div>
|
|
||||||
{stepErrors.map((error) => (
|
|
||||||
<StepError key={error.step_id} stepId={error.step_id} />
|
|
||||||
))}
|
|
||||||
</Composite>
|
|
||||||
</ErrorsCompositeContext.Provider>
|
|
||||||
</Popover>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,118 +1,43 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
import { Button, NavigableMenu, TextControl } from '@wordpress/components';
|
import { Button, NavigableMenu, TextControl } from '@wordpress/components';
|
||||||
import { dispatch, useDispatch, useSelect } from '@wordpress/data';
|
import { useDispatch, useSelect } from '@wordpress/data';
|
||||||
import { PinnedItems } from '@wordpress/interface';
|
import { PinnedItems } from '@wordpress/interface';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { DocumentActions } from './document_actions';
|
import { DocumentActions } from './document_actions';
|
||||||
import { Errors } from './errors';
|
|
||||||
import { InserterToggle } from './inserter_toggle';
|
import { InserterToggle } from './inserter_toggle';
|
||||||
import { MoreMenu } from './more_menu';
|
import { MoreMenu } from './more_menu';
|
||||||
import { storeName } from '../../store';
|
import { store, storeName } from '../../store';
|
||||||
import { WorkflowStatus } from '../../../listing/workflow';
|
import { WorkflowStatus } from '../../../listing/workflow';
|
||||||
import { DeactivateModal } from '../modals/deactivate-modal';
|
|
||||||
|
|
||||||
// See:
|
// See:
|
||||||
// https://github.com/WordPress/gutenberg/blob/9601a33e30ba41bac98579c8d822af63dd961488/packages/edit-post/src/components/header/index.js
|
// https://github.com/WordPress/gutenberg/blob/9601a33e30ba41bac98579c8d822af63dd961488/packages/edit-post/src/components/header/index.js
|
||||||
// https://github.com/WordPress/gutenberg/blob/0ee78b1bbe9c6f3e6df99f3b967132fa12bef77d/packages/edit-site/src/components/header/index.js
|
// https://github.com/WordPress/gutenberg/blob/0ee78b1bbe9c6f3e6df99f3b967132fa12bef77d/packages/edit-site/src/components/header/index.js
|
||||||
|
|
||||||
function ActivateButton({ onClick }): JSX.Element {
|
function ActivateButton(): JSX.Element {
|
||||||
const { errors } = useSelect(
|
const { activate } = useDispatch(store);
|
||||||
(select) => ({
|
|
||||||
errors: select(storeName).getErrors(),
|
|
||||||
}),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button isPrimary className="editor-post-publish-button" onClick={activate}>
|
||||||
variant="primary"
|
Activate
|
||||||
className="editor-post-publish-button"
|
|
||||||
onClick={onClick}
|
|
||||||
disabled={!!errors}
|
|
||||||
>
|
|
||||||
{__('Activate', 'mailpoet')}
|
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function UpdateButton(): JSX.Element {
|
function UpdateButton(): JSX.Element {
|
||||||
const { save } = useDispatch(storeName);
|
const { activate } = useDispatch(store);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button isPrimary className="editor-post-publish-button" onClick={activate}>
|
||||||
variant="primary"
|
Update
|
||||||
className="editor-post-publish-button"
|
|
||||||
onClick={save}
|
|
||||||
>
|
|
||||||
{__('Update', 'mailpoet')}
|
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SaveDraftButton(): JSX.Element {
|
export function Header(): JSX.Element {
|
||||||
const { save } = useDispatch(storeName);
|
const { setWorkflowName } = useDispatch(store);
|
||||||
|
|
||||||
return (
|
|
||||||
<Button variant="tertiary" onClick={save}>
|
|
||||||
{__('Save draft', 'mailpoet')}
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function DeactivateButton(): JSX.Element {
|
|
||||||
const [showDeactivateModal, setShowDeactivateModal] = useState(false);
|
|
||||||
const [isBusy, setIsBusy] = useState(false);
|
|
||||||
const { hasUsersInProgress } = useSelect(
|
|
||||||
(select) => ({
|
|
||||||
hasUsersInProgress:
|
|
||||||
select(storeName).getWorkflowData().stats.totals.in_progress > 0,
|
|
||||||
}),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const deactivateOrShowModal = () => {
|
|
||||||
if (hasUsersInProgress) {
|
|
||||||
setShowDeactivateModal(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setIsBusy(true);
|
|
||||||
void dispatch(storeName).deactivate();
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{showDeactivateModal && (
|
|
||||||
<DeactivateModal
|
|
||||||
onClose={() => {
|
|
||||||
setShowDeactivateModal(false);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<Button
|
|
||||||
isBusy={isBusy}
|
|
||||||
variant="tertiary"
|
|
||||||
onClick={deactivateOrShowModal}
|
|
||||||
>
|
|
||||||
{__('Deactivate', 'mailpoet')}
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
showInserterToggle: boolean;
|
|
||||||
toggleActivatePanel: () => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Header({
|
|
||||||
showInserterToggle,
|
|
||||||
toggleActivatePanel,
|
|
||||||
}: Props): JSX.Element {
|
|
||||||
const { setWorkflowName } = useDispatch(storeName);
|
|
||||||
const { workflowName, workflowStatus } = useSelect(
|
const { workflowName, workflowStatus } = useSelect(
|
||||||
(select) => ({
|
(select) => ({
|
||||||
workflowName: select(storeName).getWorkflowData().name,
|
workflowName: select(store).getWorkflowData().name,
|
||||||
workflowStatus: select(storeName).getWorkflowData().status,
|
workflowStatus: select(store).getWorkflowData().status,
|
||||||
}),
|
}),
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
@ -125,7 +50,7 @@ export function Header({
|
|||||||
orientation="horizontal"
|
orientation="horizontal"
|
||||||
role="toolbar"
|
role="toolbar"
|
||||||
>
|
>
|
||||||
{showInserterToggle && <InserterToggle />}
|
<InserterToggle />
|
||||||
</NavigableMenu>
|
</NavigableMenu>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -134,14 +59,13 @@ export function Header({
|
|||||||
{() => (
|
{() => (
|
||||||
<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')}
|
||||||
</div>
|
</div>
|
||||||
<TextControl
|
<TextControl
|
||||||
value={workflowName}
|
value={workflowName}
|
||||||
onChange={(newName) => setWorkflowName(newName)}
|
onChange={(newName) => setWorkflowName(newName)}
|
||||||
help={__(
|
help={__(
|
||||||
`Give the automation a name that indicates its purpose. E.g. "Abandoned cart recovery"`,
|
`Give the automation a name that indicates its purpose. E.g. "Abandoned cart recovery"`,
|
||||||
'mailpoet',
|
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -151,19 +75,9 @@ export function Header({
|
|||||||
|
|
||||||
<div className="edit-site-header_end">
|
<div className="edit-site-header_end">
|
||||||
<div className="edit-site-header__actions">
|
<div className="edit-site-header__actions">
|
||||||
<Errors />
|
<Button isTertiary>{__('Save Draft')}</Button>
|
||||||
{workflowStatus !== WorkflowStatus.ACTIVE && (
|
{workflowStatus !== WorkflowStatus.ACTIVE && <ActivateButton />}
|
||||||
<>
|
{workflowStatus === WorkflowStatus.ACTIVE && <UpdateButton />}
|
||||||
<SaveDraftButton />
|
|
||||||
<ActivateButton onClick={toggleActivatePanel} />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{workflowStatus === WorkflowStatus.ACTIVE && (
|
|
||||||
<>
|
|
||||||
<DeactivateButton />
|
|
||||||
<UpdateButton />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
<PinnedItems.Slot scope={storeName} />
|
<PinnedItems.Slot scope={storeName} />
|
||||||
<MoreMenu />
|
<MoreMenu />
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,7 +2,7 @@ import { Button, ToolbarItem } from '@wordpress/components';
|
|||||||
import { useSelect, useDispatch } from '@wordpress/data';
|
import { useSelect, useDispatch } from '@wordpress/data';
|
||||||
import { __, _x } from '@wordpress/i18n';
|
import { __, _x } from '@wordpress/i18n';
|
||||||
import { plus } from '@wordpress/icons';
|
import { plus } from '@wordpress/icons';
|
||||||
import { storeName } from '../../store';
|
import { store } from '../../store';
|
||||||
|
|
||||||
// See:
|
// See:
|
||||||
// https://github.com/WordPress/gutenberg/blob/5caeae34b3fb303761e3b9432311b26f4e5ea3a6/packages/edit-post/src/components/header/header-toolbar/index.js
|
// https://github.com/WordPress/gutenberg/blob/5caeae34b3fb303761e3b9432311b26f4e5ea3a6/packages/edit-post/src/components/header/header-toolbar/index.js
|
||||||
@ -11,13 +11,13 @@ import { storeName } from '../../store';
|
|||||||
export function InserterToggle(): JSX.Element {
|
export function InserterToggle(): JSX.Element {
|
||||||
const { isInserterOpened, showIconLabels } = useSelect(
|
const { isInserterOpened, showIconLabels } = useSelect(
|
||||||
(select) => ({
|
(select) => ({
|
||||||
isInserterOpened: select(storeName).isInserterSidebarOpened(),
|
isInserterOpened: select(store).isInserterSidebarOpened(),
|
||||||
showIconLabels: select(storeName).isFeatureActive('showIconLabels'),
|
showIconLabels: select(store).isFeatureActive('showIconLabels'),
|
||||||
}),
|
}),
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
const { toggleInserterSidebar } = useDispatch(storeName);
|
const { toggleInserterSidebar } = useDispatch(store);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ToolbarItem
|
<ToolbarItem
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import { MenuGroup, MenuItem } from '@wordpress/components';
|
import { MenuGroup } from '@wordpress/components';
|
||||||
import { displayShortcut } from '@wordpress/keycodes';
|
import { displayShortcut } from '@wordpress/keycodes';
|
||||||
import { __, _x } from '@wordpress/i18n';
|
import { __, _x } from '@wordpress/i18n';
|
||||||
import { MoreMenuDropdown } from '@wordpress/interface';
|
import { MoreMenuDropdown } from '@wordpress/interface';
|
||||||
import { PreferenceToggleMenuItem } from '@wordpress/preferences';
|
import { PreferenceToggleMenuItem } from '@wordpress/preferences';
|
||||||
import { storeName } from '../../store';
|
import { storeName } from '../../store';
|
||||||
import { MailPoet } from '../../../../mailpoet';
|
|
||||||
|
|
||||||
// See:
|
// See:
|
||||||
// https://github.com/WordPress/gutenberg/blob/9601a33e30ba41bac98579c8d822af63dd961488/packages/edit-post/src/components/header/more-menu/index.js
|
// https://github.com/WordPress/gutenberg/blob/9601a33e30ba41bac98579c8d822af63dd961488/packages/edit-post/src/components/header/more-menu/index.js
|
||||||
@ -19,28 +18,17 @@ export function MoreMenu(): JSX.Element {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{() => (
|
{() => (
|
||||||
<>
|
<MenuGroup label={_x('View', 'noun')}>
|
||||||
<MenuGroup label={_x('View', 'noun')}>
|
<PreferenceToggleMenuItem
|
||||||
<PreferenceToggleMenuItem
|
scope={storeName}
|
||||||
scope={storeName}
|
name="fullscreenMode"
|
||||||
name="fullscreenMode"
|
label={__('Fullscreen mode')}
|
||||||
label={__('Fullscreen mode')}
|
info={__('Work without distraction')}
|
||||||
info={__('Work without distraction')}
|
messageActivated={__('Fullscreen mode activated')}
|
||||||
messageActivated={__('Fullscreen mode activated')}
|
messageDeactivated={__('Fullscreen mode deactivated')}
|
||||||
messageDeactivated={__('Fullscreen mode deactivated')}
|
shortcut={displayShortcut.secondary('f')}
|
||||||
shortcut={displayShortcut.secondary('f')}
|
/>
|
||||||
/>
|
</MenuGroup>
|
||||||
</MenuGroup>
|
|
||||||
<MenuGroup>
|
|
||||||
<MenuItem
|
|
||||||
onClick={() => {
|
|
||||||
window.location.href = MailPoet.urls.automationListing;
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{__('View all automations', 'mailpoet')}
|
|
||||||
</MenuItem>
|
|
||||||
</MenuGroup>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</MoreMenuDropdown>
|
</MoreMenuDropdown>
|
||||||
);
|
);
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
import { Icon } from '@wordpress/components';
|
|
||||||
import { ComponentType } from 'react';
|
|
||||||
|
|
||||||
export type ColoredIconProps = {
|
|
||||||
width: string;
|
|
||||||
height: string;
|
|
||||||
background: string;
|
|
||||||
foreground: string;
|
|
||||||
icon: ComponentType;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ColoredIcon({
|
|
||||||
foreground,
|
|
||||||
background,
|
|
||||||
...iconProps
|
|
||||||
}: ColoredIconProps): JSX.Element {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="mailpoet-automation-colored-icon"
|
|
||||||
style={{
|
|
||||||
width: iconProps.width,
|
|
||||||
height: iconProps.height,
|
|
||||||
backgroundColor: background,
|
|
||||||
fill: foreground,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Icon {...iconProps} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
@ -0,0 +1,20 @@
|
|||||||
|
export function DelayIcon(): JSX.Element {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width="41"
|
||||||
|
height="41"
|
||||||
|
viewBox="0 0 41 41"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M0.796875 20.5C0.796875 9.45431 9.75118 0.5 20.7969 0.5C31.8426 0.5 40.7969 9.45431 40.7969 20.5C40.7969 31.5457 31.8426 40.5 20.7969 40.5C9.75118 40.5 0.796875 31.5457 0.796875 20.5Z"
|
||||||
|
fill="#F7EDF7"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M20.7972 11.1665C15.6639 11.1665 11.4639 15.3665 11.4639 20.4998C11.4639 25.6332 15.6639 29.8332 20.7972 29.8332C25.9305 29.8332 30.1305 25.6332 30.1305 20.4998C30.1305 15.3665 25.9305 11.1665 20.7972 11.1665ZM20.7972 27.9665C16.6812 27.9665 13.3305 24.6158 13.3305 20.4998C13.3305 16.3838 16.6812 13.0332 20.7972 13.0332C24.9132 13.0332 28.2639 16.3838 28.2639 20.4998C28.2639 24.6158 24.9132 27.9665 20.7972 27.9665ZM21.2639 15.8332H19.8639V21.4332L24.7172 24.4198L25.4639 23.2065L21.2639 20.6865V15.8332Z"
|
||||||
|
fill="#7F54B3"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
export function EmailIcon(): JSX.Element {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width="41"
|
||||||
|
height="41"
|
||||||
|
viewBox="0 0 41 41"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M0.5 20.5C0.5 9.45431 9.45431 0.5 20.5 0.5C31.5457 0.5 40.5 9.45431 40.5 20.5C40.5 31.5457 31.5457 40.5 20.5 40.5C9.45431 40.5 0.5 31.5457 0.5 20.5Z"
|
||||||
|
fill="#FCF9E8"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M27.4998 14.375H13.4998C12.6944 14.375 12.0415 15.0279 12.0415 15.8333V25.1667C12.0415 25.9721 12.6944 26.625 13.4998 26.625H27.4998C28.3053 26.625 28.9582 25.9721 28.9582 25.1667V15.8333C28.9582 15.0279 28.3053 14.375 27.4998 14.375Z"
|
||||||
|
stroke="#996800"
|
||||||
|
strokeWidth="1.5"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M12.3335 14.6665L20.5002 21.6665L28.6668 14.6665"
|
||||||
|
stroke="#996800"
|
||||||
|
strokeWidth="1.5"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
@ -1,2 +1,3 @@
|
|||||||
|
export { DelayIcon } from './delay';
|
||||||
|
export { EmailIcon } from './email';
|
||||||
export { TriggerIcon } from './trigger';
|
export { TriggerIcon } from './trigger';
|
||||||
export { ColoredIcon } from './colored-icon';
|
|
||||||
|
@ -1,8 +1,24 @@
|
|||||||
export function TriggerIcon(): JSX.Element {
|
export function TriggerIcon(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<svg viewBox="0 0 24 18" xmlns="http://www.w3.org/2000/svg">
|
<svg
|
||||||
<path d="M16.1135 1.06667L22.6469 7.6C23.4635 8.3 23.4635 9.7 22.5302 10.5167L15.9969 17.05C15.6469 17.4 15.0635 17.6333 14.5968 17.6333C14.1302 17.6333 13.5468 17.4 13.1968 17.05L6.66352 10.5167C5.84685 9.7 5.84685 8.41667 6.66352 7.6L13.1968 1.06667C14.0135 0.25 15.2968 0.25 16.1135 1.06667Z" />
|
width="40"
|
||||||
<path d="M9.46352 1.41667L2.11352 8.76667C1.99685 8.88333 1.99685 9.11667 2.23018 9.11667L9.58018 16.4667L8.29685 17.75L0.946851 10.5167C0.130184 9.7 0.130184 8.41667 0.946851 7.6L8.29685 0.25L9.46352 1.41667Z" />
|
height="41"
|
||||||
|
viewBox="0 0 40 41"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M0 20.5C0 9.45431 8.95431 0.5 20 0.5C31.0457 0.5 40 9.45431 40 20.5C40 31.5457 31.0457 40.5 20 40.5C8.95431 40.5 0 31.5457 0 20.5Z"
|
||||||
|
fill="#F0F6FC"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M24.3163 12.5667L30.8496 19.1C31.6663 19.8 31.6663 21.2 30.7329 22.0167L24.1996 28.55C23.8496 28.9 23.2663 29.1333 22.7996 29.1333C22.3329 29.1333 21.7496 28.9 21.3996 28.55L14.8663 22.0167C14.0496 21.2 14.0496 19.9167 14.8663 19.1L21.3996 12.5667C22.2163 11.75 23.4996 11.75 24.3163 12.5667Z"
|
||||||
|
fill="#2271B1"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M17.6663 12.9167L10.3163 20.2667C10.1996 20.3833 10.1996 20.6167 10.4329 20.6167L17.7829 27.9667L16.4996 29.25L9.14961 22.0167C8.33294 21.2 8.33294 19.9167 9.14961 19.1L16.4996 11.75L17.6663 12.9167Z"
|
||||||
|
fill="#2271B1"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,66 +1,28 @@
|
|||||||
import { useCallback, useRef, useState } from 'react';
|
|
||||||
import { Popover } from '@wordpress/components';
|
import { Popover } from '@wordpress/components';
|
||||||
import { useDispatch, useSelect } from '@wordpress/data';
|
import { dispatch, useSelect } from '@wordpress/data';
|
||||||
import { __ } from '@wordpress/i18n';
|
|
||||||
import { Hooks } from 'wp-js-hooks';
|
|
||||||
import { PremiumModal } from 'common/premium_modal';
|
|
||||||
import { Inserter } from '../inserter';
|
import { Inserter } from '../inserter';
|
||||||
import { Item } from '../inserter/item';
|
import { store } from '../../store';
|
||||||
import { storeName } from '../../store';
|
|
||||||
|
|
||||||
export function InserterPopover(): JSX.Element | null {
|
export function InserterPopover(): JSX.Element | null {
|
||||||
const popoverRef = useRef<HTMLDivElement>();
|
const { inserterPopoverAnchor } = useSelect(
|
||||||
const [showModal, setShowModal] = useState(false);
|
|
||||||
const { inserterPopover } = useSelect(
|
|
||||||
(select) => ({
|
(select) => ({
|
||||||
inserterPopover: select(storeName).getInserterPopover(),
|
inserterPopoverAnchor: select(store).getInserterPopoverAnchor(),
|
||||||
}),
|
}),
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
const { setInserterPopover } = useDispatch(storeName);
|
|
||||||
|
|
||||||
const onInsert = useCallback((item: Item) => {
|
const { setInserterPopoverAnchor } = dispatch(store);
|
||||||
const addStepCallback = Hooks.applyFilters(
|
|
||||||
'mailpoet.automation.workflow.add_step_callback',
|
|
||||||
() => {
|
|
||||||
setShowModal(true);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
addStepCallback(item);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
if (!inserterPopover) {
|
if (!inserterPopoverAnchor) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Popover
|
||||||
<Popover
|
anchorRect={inserterPopoverAnchor.getBoundingClientRect()}
|
||||||
ref={popoverRef}
|
onClose={() => setInserterPopoverAnchor(undefined)}
|
||||||
anchorRect={inserterPopover.anchor.getBoundingClientRect()}
|
>
|
||||||
onClose={() => {
|
<Inserter />
|
||||||
if (!showModal) {
|
</Popover>
|
||||||
setInserterPopover(undefined);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Inserter onInsert={onInsert} />
|
|
||||||
</Popover>
|
|
||||||
|
|
||||||
{showModal && (
|
|
||||||
<PremiumModal
|
|
||||||
onRequestClose={() => {
|
|
||||||
setShowModal(false);
|
|
||||||
popoverRef.current?.focus();
|
|
||||||
}}
|
|
||||||
tracking={{
|
|
||||||
utm_medium: 'upsell_modal',
|
|
||||||
utm_campaign: 'add_automation_step',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{__('You cannot add a new step to the automation.', 'mailpoet')}
|
|
||||||
</PremiumModal>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
import { Item } from './item';
|
|
||||||
|
|
||||||
export type Group = {
|
|
||||||
type: string;
|
|
||||||
title?: string;
|
|
||||||
label: string;
|
|
||||||
items: Item[];
|
|
||||||
};
|
|
@ -1,15 +1,14 @@
|
|||||||
import { forwardRef, Fragment, useCallback, useMemo } from 'react';
|
import { forwardRef, useCallback, useMemo } from 'react';
|
||||||
import { SearchControl } from '@wordpress/components';
|
import { SearchControl } from '@wordpress/components';
|
||||||
import { useSelect } from '@wordpress/data';
|
import { useSelect } from '@wordpress/data';
|
||||||
import { useRef, useImperativeHandle, useState } from '@wordpress/element';
|
import { useRef, useImperativeHandle, useState } from '@wordpress/element';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { blockDefault, Icon } from '@wordpress/icons';
|
import { blockDefault, Icon } from '@wordpress/icons';
|
||||||
import { Group } from './group';
|
|
||||||
import { Item } from './item';
|
import { Item } from './item';
|
||||||
import { StepInfoPanel } from './step_info_panel';
|
import { StepInfoPanel } from './step_info_panel';
|
||||||
import { StepList } from './step_list';
|
import { StepList } from './step_list';
|
||||||
import { InserterListbox } from '../inserter-listbox';
|
import { InserterListbox } from '../inserter-listbox';
|
||||||
import { storeName } from '../../store';
|
import { store } from '../../store';
|
||||||
|
|
||||||
// See: https://github.com/WordPress/gutenberg/blob/628ae68152f572d0b395bb15c0f71b8821e7f130/packages/block-editor/src/components/inserter/menu.js
|
// See: https://github.com/WordPress/gutenberg/blob/628ae68152f572d0b395bb15c0f71b8821e7f130/packages/block-editor/src/components/inserter/menu.js
|
||||||
|
|
||||||
@ -18,50 +17,18 @@ const filterItems = (value: string, item: Item[]): Item[] =>
|
|||||||
step.title.toLowerCase().includes(value.trim().toLowerCase()),
|
step.title.toLowerCase().includes(value.trim().toLowerCase()),
|
||||||
);
|
);
|
||||||
|
|
||||||
type Props = {
|
export const Inserter = forwardRef((_, ref): JSX.Element => {
|
||||||
onInsert?: (item: Item) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Inserter = forwardRef(({ onInsert }: Props, ref): JSX.Element => {
|
|
||||||
const [filterValue, setFilterValue] = useState('');
|
const [filterValue, setFilterValue] = useState('');
|
||||||
const [hoveredItem, setHoveredItem] = useState(null);
|
const [hoveredItem, setHoveredItem] = useState(null);
|
||||||
|
|
||||||
const { steps, type } = useSelect(
|
const { actionSteps, logicalSteps } = useSelect(
|
||||||
(select) => ({
|
(select) => ({
|
||||||
steps: select(storeName).getSteps(),
|
actionSteps: select(store).getInserterActionSteps(),
|
||||||
type: select(storeName).getInserterPopover().type,
|
logicalSteps: select(store).getInserterLogicalSteps(),
|
||||||
}),
|
}),
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
const groups: Group[] = useMemo(
|
|
||||||
() =>
|
|
||||||
type === 'triggers'
|
|
||||||
? [
|
|
||||||
{
|
|
||||||
type: 'triggers',
|
|
||||||
title: undefined,
|
|
||||||
label: __('Triggers', 'mailpoet'),
|
|
||||||
items: steps.filter(({ group }) => group === 'triggers'),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
: [
|
|
||||||
{
|
|
||||||
type: 'actions',
|
|
||||||
title: __('Actions', 'mailpoet'),
|
|
||||||
label: __('Actions', 'mailpoet'),
|
|
||||||
items: steps.filter(({ group }) => group === 'actions'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'logical',
|
|
||||||
title: __('Logical', 'mailpoet'),
|
|
||||||
label: __('Logical', 'mailpoet'),
|
|
||||||
items: steps.filter(({ group }) => group === 'logical'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[steps, type],
|
|
||||||
);
|
|
||||||
|
|
||||||
const onHover = useCallback(
|
const onHover = useCallback(
|
||||||
(item) => {
|
(item) => {
|
||||||
setHoveredItem(item);
|
setHoveredItem(item);
|
||||||
@ -76,13 +43,13 @@ export const Inserter = forwardRef(({ onInsert }: Props, ref): JSX.Element => {
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const filteredGroups = useMemo(
|
const filteredActionSteps = useMemo(
|
||||||
() =>
|
() => filterItems(filterValue, actionSteps),
|
||||||
groups.map((group) => ({
|
[actionSteps, filterValue],
|
||||||
...group,
|
);
|
||||||
items: filterItems(filterValue, group.items),
|
const filteredLogicalSteps = useMemo(
|
||||||
})),
|
() => filterItems(filterValue, logicalSteps),
|
||||||
[filterValue, groups],
|
[filterValue, logicalSteps],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -103,41 +70,52 @@ export const Inserter = forwardRef(({ onInsert }: Props, ref): JSX.Element => {
|
|||||||
|
|
||||||
<div className="block-editor-inserter__block-list">
|
<div className="block-editor-inserter__block-list">
|
||||||
<InserterListbox>
|
<InserterListbox>
|
||||||
{filteredGroups.map(
|
{filteredActionSteps.length > 0 && (
|
||||||
(group) =>
|
<>
|
||||||
group.items.length > 0 && (
|
<div className="block-editor-inserter__panel-header">
|
||||||
<Fragment key={group.type}>
|
<h2 className="block-editor-inserter__panel-title">
|
||||||
{group.title && (
|
<div>Actions</div>
|
||||||
<div className="block-editor-inserter__panel-header">
|
</h2>
|
||||||
<h2 className="block-editor-inserter__panel-title">
|
</div>
|
||||||
<div>{group.title}</div>
|
<div className="block-editor-inserter__panel-content">
|
||||||
</h2>
|
<StepList
|
||||||
</div>
|
items={filteredActionSteps}
|
||||||
)}
|
onHover={onHover}
|
||||||
<div className="block-editor-inserter__panel-content">
|
onSelect={() => {}}
|
||||||
<StepList
|
label="A"
|
||||||
items={group.items}
|
/>
|
||||||
onHover={onHover}
|
</div>
|
||||||
onSelect={(item: Item) => onInsert(item)}
|
</>
|
||||||
label={group.label}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Fragment>
|
|
||||||
),
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{filteredGroups.reduce(
|
{filteredLogicalSteps.length > 0 && (
|
||||||
(sum, { items }) => sum + items.length,
|
<>
|
||||||
0,
|
<div className="block-editor-inserter__panel-header">
|
||||||
) === 0 && (
|
<h2 className="block-editor-inserter__panel-title">
|
||||||
<div className="block-editor-inserter__no-results">
|
<div>Logical</div>
|
||||||
<Icon
|
</h2>
|
||||||
className="block-editor-inserter__no-results-icon"
|
</div>
|
||||||
icon={blockDefault}
|
<div className="block-editor-inserter__panel-content">
|
||||||
/>
|
<StepList
|
||||||
<p>{__('No results found.')}</p>
|
items={filteredLogicalSteps}
|
||||||
</div>
|
onHover={onHover}
|
||||||
|
onSelect={() => {}}
|
||||||
|
label="B"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{filteredActionSteps.length === 0 &&
|
||||||
|
filteredLogicalSteps.length === 0 && (
|
||||||
|
<div className="block-editor-inserter__no-results">
|
||||||
|
<Icon
|
||||||
|
className="block-editor-inserter__no-results-icon"
|
||||||
|
icon={blockDefault}
|
||||||
|
/>
|
||||||
|
<p>{__('No results found.')}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</InserterListbox>
|
</InserterListbox>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import { ComponentType } from 'react';
|
|
||||||
|
|
||||||
export type Item = {
|
export type Item = {
|
||||||
key: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
icon: JSX.Element;
|
||||||
description: string;
|
description: string;
|
||||||
icon: ComponentType | JSX.Element;
|
isDisabled: boolean;
|
||||||
isDisabled?: boolean;
|
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
|
// See: https://github.com/WordPress/gutenberg/blob/9601a33e30ba41bac98579c8d822af63dd961488/packages/block-editor/src/components/block-icon/index.js
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
icon: ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function StepIcon({ icon }: Props): JSX.Element {
|
||||||
|
return <span className="block-editor-block-icon">{icon}</span>;
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
|
import { StepIcon } from './step_icon';
|
||||||
import { Item } from './item';
|
import { Item } from './item';
|
||||||
import { StepIcon } from '../step-icon';
|
|
||||||
|
|
||||||
// See: https://github.com/WordPress/gutenberg/blob/9601a33e30ba41bac98579c8d822af63dd961488/packages/block-editor/src/components/inserter/preview-panel.js
|
// See: https://github.com/WordPress/gutenberg/blob/9601a33e30ba41bac98579c8d822af63dd961488/packages/block-editor/src/components/inserter/preview-panel.js
|
||||||
|
|
||||||
|
@ -46,9 +46,9 @@ export function StepList({
|
|||||||
<InserterListboxRow key={i}>
|
<InserterListboxRow key={i}>
|
||||||
{row.map((item, j) => (
|
{row.map((item, j) => (
|
||||||
<InserterListItem
|
<InserterListItem
|
||||||
key={item.key}
|
key={item.id}
|
||||||
item={item}
|
item={item}
|
||||||
className={getBlockMenuDefaultClassName(item.key)}
|
className={getBlockMenuDefaultClassName(item.id)}
|
||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
onHover={onHover}
|
onHover={onHover}
|
||||||
isDraggable={isDraggable}
|
isDraggable={isDraggable}
|
||||||
|
@ -3,8 +3,8 @@ import { ComponentProps } from 'react';
|
|||||||
import { useRef, memo } from '@wordpress/element';
|
import { useRef, memo } from '@wordpress/element';
|
||||||
import { ENTER } from '@wordpress/keycodes';
|
import { ENTER } from '@wordpress/keycodes';
|
||||||
import { Item } from './item';
|
import { Item } from './item';
|
||||||
|
import { StepIcon } from './step_icon';
|
||||||
import { InserterListboxItem } from '../inserter-listbox/listbox_item';
|
import { InserterListboxItem } from '../inserter-listbox/listbox_item';
|
||||||
import { StepIcon } from '../step-icon';
|
|
||||||
|
|
||||||
// See: https://github.com/WordPress/gutenberg/blob/628ae68152f572d0b395bb15c0f71b8821e7f130/packages/block-editor/src/components/inserter-list-item/index.js
|
// See: https://github.com/WordPress/gutenberg/blob/628ae68152f572d0b395bb15c0f71b8821e7f130/packages/block-editor/src/components/inserter-list-item/index.js
|
||||||
|
|
||||||
@ -15,9 +15,7 @@ const isAppleOS = (): boolean => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
type ListboxItemProps = ComponentProps<typeof InserterListboxItem>;
|
type Props = ComponentProps<typeof InserterListboxItem> & {
|
||||||
|
|
||||||
type Props = Omit<ListboxItemProps, 'onSelect' | 'onHover'> & {
|
|
||||||
item: Item;
|
item: Item;
|
||||||
onSelect: (item: Item, isModifierKey: boolean) => void;
|
onSelect: (item: Item, isModifierKey: boolean) => void;
|
||||||
onHover: (item: Item) => void;
|
onHover: (item: Item) => void;
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
store as keyboardShortcutsStore,
|
store as keyboardShortcutsStore,
|
||||||
} from '@wordpress/keyboard-shortcuts';
|
} from '@wordpress/keyboard-shortcuts';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { stepSidebarKey, storeName, workflowSidebarKey } from '../../store';
|
import { stepSidebarKey, store, workflowSidebarKey } from '../../store';
|
||||||
|
|
||||||
// See:
|
// See:
|
||||||
// https://github.com/WordPress/gutenberg/blob/9601a33e30ba41bac98579c8d822af63dd961488/packages/edit-post/src/components/keyboard-shortcuts/index.js
|
// https://github.com/WordPress/gutenberg/blob/9601a33e30ba41bac98579c8d822af63dd961488/packages/edit-post/src/components/keyboard-shortcuts/index.js
|
||||||
@ -13,16 +13,16 @@ import { stepSidebarKey, storeName, workflowSidebarKey } from '../../store';
|
|||||||
|
|
||||||
export function KeyboardShortcuts(): null {
|
export function KeyboardShortcuts(): null {
|
||||||
const { isSidebarOpened, selectedStep } = useSelect((select) => ({
|
const { isSidebarOpened, selectedStep } = useSelect((select) => ({
|
||||||
isSidebarOpened: select(storeName).isSidebarOpened,
|
isSidebarOpened: select(store).isSidebarOpened,
|
||||||
selectedStep: select(storeName).getSelectedStep,
|
selectedStep: select(store).getSelectedStep,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const { openSidebar, closeSidebar, toggleFeature } = useDispatch(storeName);
|
const { openSidebar, closeSidebar, toggleFeature } = useDispatch(store);
|
||||||
|
|
||||||
const { registerShortcut } = useDispatch(keyboardShortcutsStore);
|
const { registerShortcut } = useDispatch(keyboardShortcutsStore);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
void registerShortcut({
|
registerShortcut({
|
||||||
name: 'mailpoet/automation-editor/toggle-fullscreen',
|
name: 'mailpoet/automation-editor/toggle-fullscreen',
|
||||||
category: 'global',
|
category: 'global',
|
||||||
description: __('Toggle fullscreen mode.'),
|
description: __('Toggle fullscreen mode.'),
|
||||||
@ -32,7 +32,7 @@ export function KeyboardShortcuts(): null {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
void registerShortcut({
|
registerShortcut({
|
||||||
name: 'mailpoet/automation-editor/toggle-sidebar',
|
name: 'mailpoet/automation-editor/toggle-sidebar',
|
||||||
category: 'global',
|
category: 'global',
|
||||||
description: __('Show or hide the settings sidebar.'),
|
description: __('Show or hide the settings sidebar.'),
|
||||||
|
@ -1,115 +0,0 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
import { Button, Modal } from '@wordpress/components';
|
|
||||||
import { __, sprintf } from '@wordpress/i18n';
|
|
||||||
import { dispatch, useSelect } from '@wordpress/data';
|
|
||||||
import { storeName } from '../../store';
|
|
||||||
import { WorkflowStatus } from '../../../listing/workflow';
|
|
||||||
|
|
||||||
export function DeactivateModal({ onClose }): JSX.Element {
|
|
||||||
const { workflowName } = useSelect(
|
|
||||||
(select) => ({
|
|
||||||
workflowName: select(storeName).getWorkflowData().name,
|
|
||||||
}),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
const [selected, setSelected] = useState<
|
|
||||||
WorkflowStatus.INACTIVE | WorkflowStatus.DEACTIVATING
|
|
||||||
>(WorkflowStatus.DEACTIVATING);
|
|
||||||
const [isBusy, setIsBusy] = useState<boolean>(false);
|
|
||||||
// translators: %s is the name of the automation.
|
|
||||||
const title = sprintf(
|
|
||||||
__('Deactivate the "%s" automation?', 'mailpoet'),
|
|
||||||
workflowName,
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal
|
|
||||||
className="mailpoet-automatoin-deactivate-modal"
|
|
||||||
title={title}
|
|
||||||
onRequestClose={onClose}
|
|
||||||
>
|
|
||||||
{__(
|
|
||||||
"Some subscribers entered but have not finished the flow. Let's decide what to do in this case.",
|
|
||||||
'mailpoet',
|
|
||||||
)}
|
|
||||||
<ul className="mailpoet-automation-options">
|
|
||||||
<li>
|
|
||||||
<label
|
|
||||||
className={
|
|
||||||
selected === WorkflowStatus.DEACTIVATING
|
|
||||||
? 'mailpoet-automation-option active'
|
|
||||||
: 'mailpoet-automation-option'
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
disabled={isBusy}
|
|
||||||
name="deactivation-method"
|
|
||||||
checked={selected === WorkflowStatus.DEACTIVATING}
|
|
||||||
onChange={() => setSelected(WorkflowStatus.DEACTIVATING)}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
<span>
|
|
||||||
<strong>
|
|
||||||
{__('Let entered subscribers finish the flow', 'mailpoet')}
|
|
||||||
</strong>
|
|
||||||
{__(
|
|
||||||
"New subscribers won't enter, but recently entered could proceed.",
|
|
||||||
'mailpoet',
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<label
|
|
||||||
className={
|
|
||||||
selected === WorkflowStatus.INACTIVE
|
|
||||||
? 'mailpoet-automation-option active'
|
|
||||||
: 'mailpoet-automation-option'
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
disabled={isBusy}
|
|
||||||
name="deactivation-method"
|
|
||||||
checked={selected === WorkflowStatus.INACTIVE}
|
|
||||||
onChange={() => setSelected(WorkflowStatus.INACTIVE)}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
<span>
|
|
||||||
<strong>
|
|
||||||
{__('Stop automation for all subscribers', 'mailpoet')}
|
|
||||||
</strong>
|
|
||||||
{__(
|
|
||||||
'Automation will be deactivated for all the subscribers immediately.',
|
|
||||||
'mailpoet',
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
isBusy={isBusy}
|
|
||||||
variant="primary"
|
|
||||||
onClick={() => {
|
|
||||||
setIsBusy(true);
|
|
||||||
if (selected === WorkflowStatus.DEACTIVATING) {
|
|
||||||
// @ToDo Use the correct method provided in MAILPOET-4731
|
|
||||||
dispatch(storeName).deactivate();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dispatch(storeName).deactivate();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{__('Deactivate automation', 'mailpoet')}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button disabled={isBusy} variant="tertiary" onClick={onClose}>
|
|
||||||
{__('Cancel', 'mailpoet')}
|
|
||||||
</Button>
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
import { NoticeList, SnackbarList } from '@wordpress/components';
|
|
||||||
import { StoreDescriptor, useSelect, useDispatch } from '@wordpress/data';
|
|
||||||
import { store as noticesStore } from '@wordpress/notices';
|
|
||||||
|
|
||||||
// See: https://github.com/WordPress/gutenberg/blob/5be0ec4153c3adf9f0f2513239f4f7a358ba7948/packages/editor/src/components/editor-notices/index.js
|
|
||||||
|
|
||||||
export function EditorNotices(): JSX.Element {
|
|
||||||
const { notices } = useSelect(
|
|
||||||
(select) => ({
|
|
||||||
notices: select(noticesStore as StoreDescriptor).getNotices(),
|
|
||||||
}),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const { removeNotice } = useDispatch(noticesStore as StoreDescriptor);
|
|
||||||
|
|
||||||
const dismissibleNotices = notices.filter(
|
|
||||||
({ isDismissible, type }) => isDismissible && type === 'default',
|
|
||||||
);
|
|
||||||
|
|
||||||
const nonDismissibleNotices = notices.filter(
|
|
||||||
({ isDismissible, type }) => !isDismissible && type === 'default',
|
|
||||||
);
|
|
||||||
|
|
||||||
const snackbarNotices = notices.filter(({ type }) => type === 'snackbar');
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<NoticeList
|
|
||||||
notices={nonDismissibleNotices}
|
|
||||||
className="mailpoet-automation-editor-notices__notice-list"
|
|
||||||
/>
|
|
||||||
<NoticeList
|
|
||||||
notices={dismissibleNotices}
|
|
||||||
className="mailpoet-automation-editor-notices__notice-list"
|
|
||||||
onRemove={removeNotice}
|
|
||||||
/>
|
|
||||||
<SnackbarList
|
|
||||||
notices={snackbarNotices}
|
|
||||||
className="mailpoet-automation-editor-notices__snackbar-list"
|
|
||||||
onRemove={removeNotice}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,128 +0,0 @@
|
|||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { useDispatch, useSelect } from '@wordpress/data';
|
|
||||||
import { Button, Spinner } from '@wordpress/components';
|
|
||||||
import { closeSmall } from '@wordpress/icons';
|
|
||||||
import { __, sprintf } from '@wordpress/i18n';
|
|
||||||
import { storeName } from '../../store';
|
|
||||||
import { WorkflowStatus } from '../../../listing/workflow';
|
|
||||||
import { MailPoet } from '../../../../mailpoet';
|
|
||||||
|
|
||||||
function PreStep({ onClose }): JSX.Element {
|
|
||||||
const [isActivating, setIsActivating] = useState(false);
|
|
||||||
const { activate } = useDispatch(storeName);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="mailpoet-automation-activate-panel__header">
|
|
||||||
<div className="mailpoet-automation-activate-panel__header-activate-button">
|
|
||||||
<Button
|
|
||||||
variant="primary"
|
|
||||||
disabled={isActivating}
|
|
||||||
isBusy={isActivating}
|
|
||||||
autoFocus={!isActivating}
|
|
||||||
onClick={() => {
|
|
||||||
setIsActivating(true);
|
|
||||||
activate();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{isActivating && __('Activating…', 'mailpoet')}
|
|
||||||
{!isActivating && __('Activate', 'mailpoet')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mailpoet-automation-activate-panel__header-cancel-button">
|
|
||||||
<Button variant="secondary" onClick={onClose} disabled={isActivating}>
|
|
||||||
{__('Cancel', 'mailpoet')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{isActivating && (
|
|
||||||
<div className="mailpoet-automation-activate-panel__body">
|
|
||||||
<Spinner />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!isActivating && (
|
|
||||||
<div className="mailpoet-automation-activate-panel__body">
|
|
||||||
<p>
|
|
||||||
<strong>{__('Are you ready to activate?', 'mailpoet')}</strong>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
{__('Double-check your settings before activating.', 'mailpoet')}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function PostStep({ onClose }): JSX.Element {
|
|
||||||
const { workflow } = useSelect(
|
|
||||||
(select) => ({
|
|
||||||
workflow: select(storeName).getWorkflowData(),
|
|
||||||
}),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const goToListings = () => {
|
|
||||||
window.location.href = MailPoet.urls.automationListing;
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="mailpoet-automation-activate-panel__header">
|
|
||||||
<Button
|
|
||||||
icon={closeSmall}
|
|
||||||
onClick={onClose}
|
|
||||||
label={__('Close', 'mailpoet')}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mailpoet-automation-activate-panel__body">
|
|
||||||
<div className="mailpoet-automation-activate-panel__section">
|
|
||||||
{sprintf(__('"%s" is now live.', 'mailpoet'), workflow.name)}
|
|
||||||
</div>
|
|
||||||
<p>
|
|
||||||
<strong>{__("What's next?", 'mailpoet')}</strong>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
{__(
|
|
||||||
'View all your automations to track statistics and create new ones.',
|
|
||||||
'mailpoet',
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
<Button variant="secondary" onClick={goToListings}>
|
|
||||||
{__('View all automations', 'mailpoet')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ActivatePanel({ onClose }): JSX.Element {
|
|
||||||
const { workflow, errors } = useSelect(
|
|
||||||
(select) => ({
|
|
||||||
errors: select(storeName).getErrors(),
|
|
||||||
workflow: select(storeName).getWorkflowData(),
|
|
||||||
}),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (errors) {
|
|
||||||
onClose();
|
|
||||||
}
|
|
||||||
}, [errors, onClose]);
|
|
||||||
|
|
||||||
if (errors) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const isActive = workflow.status === WorkflowStatus.ACTIVE;
|
|
||||||
return (
|
|
||||||
<div className="mailpoet-automation-activate-panel">
|
|
||||||
{isActive && <PostStep onClose={onClose} />}
|
|
||||||
{!isActive && <PreStep onClose={onClose} />}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
export * from './plain-body-title';
|
|
||||||
export * from './title-action-button';
|
|
@ -1,17 +0,0 @@
|
|||||||
import { ReactNode } from 'react';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
title: string;
|
|
||||||
children?: ReactNode;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function PlainBodyTitle({ title, children }: Props): JSX.Element {
|
|
||||||
return (
|
|
||||||
<h2 className="components-panel__body-title mailpoet-automation-panel-plain-body-title">
|
|
||||||
<div className="mailpoet-automation-panel-plain-body-title-text">
|
|
||||||
{title}
|
|
||||||
</div>
|
|
||||||
{children}
|
|
||||||
</h2>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
import { Dropdown, TextControl } from '@wordpress/components';
|
|
||||||
import { edit, Icon } from '@wordpress/icons';
|
|
||||||
import { PlainBodyTitle } from './plain-body-title';
|
|
||||||
import { TitleActionButton } from './title-action-button';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
currentName: string;
|
|
||||||
defaultName: string;
|
|
||||||
update: (value: string) => void;
|
|
||||||
};
|
|
||||||
export function StepName({
|
|
||||||
currentName,
|
|
||||||
defaultName,
|
|
||||||
update,
|
|
||||||
}: Props): JSX.Element {
|
|
||||||
return (
|
|
||||||
<Dropdown
|
|
||||||
className="mailpoet-step-name-dropdown"
|
|
||||||
contentClassName="mailpoet-step-name-popover"
|
|
||||||
position="bottom left"
|
|
||||||
renderToggle={({ isOpen, onToggle }) => (
|
|
||||||
<PlainBodyTitle
|
|
||||||
title={currentName.length > 0 ? currentName : defaultName}
|
|
||||||
>
|
|
||||||
<TitleActionButton
|
|
||||||
onClick={onToggle}
|
|
||||||
aria-expanded={isOpen}
|
|
||||||
aria-label="Edit step name"
|
|
||||||
>
|
|
||||||
<Icon icon={edit} size={16} />
|
|
||||||
</TitleActionButton>
|
|
||||||
</PlainBodyTitle>
|
|
||||||
)}
|
|
||||||
renderContent={() => (
|
|
||||||
<TextControl
|
|
||||||
label="Step name"
|
|
||||||
className="mailpoet-step-name-input"
|
|
||||||
placeholder={defaultName}
|
|
||||||
value={currentName}
|
|
||||||
onChange={update}
|
|
||||||
help="Give the automation step a name that indicates its purpose. E.g
|
|
||||||
“Abandoned cart recovery”. This name will be displayed only to you and not to the clients."
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
import { Button } from '@wordpress/components';
|
|
||||||
import { ComponentProps } from 'react';
|
|
||||||
|
|
||||||
type Props = ComponentProps<typeof Button>;
|
|
||||||
|
|
||||||
export function TitleActionButton(props: Props): JSX.Element {
|
|
||||||
return (
|
|
||||||
<div className="mailpoet-automation-panel-plain-body-title-action">
|
|
||||||
<Button {...props} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
import { Button } from '@wordpress/components';
|
import { Button } from '@wordpress/components';
|
||||||
import { useDispatch } from '@wordpress/data';
|
import { useDispatch } from '@wordpress/data';
|
||||||
import { stepSidebarKey, storeName, workflowSidebarKey } from '../../store';
|
import { stepSidebarKey, store, workflowSidebarKey } from '../../store';
|
||||||
|
|
||||||
// See:
|
// See:
|
||||||
// https://github.com/WordPress/gutenberg/blob/9601a33e30ba41bac98579c8d822af63dd961488/packages/edit-post/src/components/sidebar/settings-header/index.js
|
// https://github.com/WordPress/gutenberg/blob/9601a33e30ba41bac98579c8d822af63dd961488/packages/edit-post/src/components/sidebar/settings-header/index.js
|
||||||
@ -11,7 +11,7 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function Header({ sidebarKey }: Props): JSX.Element {
|
export function Header({ sidebarKey }: Props): JSX.Element {
|
||||||
const { openSidebar } = useDispatch(storeName);
|
const { openSidebar } = useDispatch(store);
|
||||||
const openWorkflowSettings = () => openSidebar(workflowSidebarKey);
|
const openWorkflowSettings = () => openSidebar(workflowSidebarKey);
|
||||||
const openStepSettings = () => openSidebar(stepSidebarKey);
|
const openStepSettings = () => openSidebar(stepSidebarKey);
|
||||||
|
|
||||||
|
@ -11,7 +11,12 @@ import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts';
|
|||||||
import { Header } from './header';
|
import { Header } from './header';
|
||||||
import { StepSidebar } from './step';
|
import { StepSidebar } from './step';
|
||||||
import { WorkflowSidebar } from './workflow';
|
import { WorkflowSidebar } from './workflow';
|
||||||
import { stepSidebarKey, storeName, workflowSidebarKey } from '../../store';
|
import {
|
||||||
|
stepSidebarKey,
|
||||||
|
store,
|
||||||
|
storeName,
|
||||||
|
workflowSidebarKey,
|
||||||
|
} from '../../store';
|
||||||
|
|
||||||
// See:
|
// See:
|
||||||
// https://github.com/WordPress/gutenberg/blob/5caeae34b3fb303761e3b9432311b26f4e5ea3a6/packages/edit-post/src/components/sidebar/plugin-sidebar/index.js
|
// https://github.com/WordPress/gutenberg/blob/5caeae34b3fb303761e3b9432311b26f4e5ea3a6/packages/edit-post/src/components/sidebar/plugin-sidebar/index.js
|
||||||
@ -37,8 +42,8 @@ export function Sidebar(props: Props): JSX.Element {
|
|||||||
sidebarKey:
|
sidebarKey:
|
||||||
select(interfaceStore).getActiveComplementaryArea(storeName) ??
|
select(interfaceStore).getActiveComplementaryArea(storeName) ??
|
||||||
workflowSidebarKey,
|
workflowSidebarKey,
|
||||||
showIconLabels: select(storeName).isFeatureActive('showIconLabels'),
|
showIconLabels: select(store).isFeatureActive('showIconLabels'),
|
||||||
workflowName: select(storeName).getWorkflowData().name,
|
workflowName: select(store).getWorkflowData().name,
|
||||||
}),
|
}),
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
@ -51,7 +56,7 @@ export function Sidebar(props: Props): JSX.Element {
|
|||||||
headerClassName="edit-site-sidebar__panel-tabs"
|
headerClassName="edit-site-sidebar__panel-tabs"
|
||||||
title={__('Settings')}
|
title={__('Settings')}
|
||||||
icon={cog}
|
icon={cog}
|
||||||
className="edit-site-sidebar mailpoet-automation-sidebar"
|
className="edit-site-sidebar"
|
||||||
panelClassName="edit-site-sidebar"
|
panelClassName="edit-site-sidebar"
|
||||||
smallScreenTitle={workflowName || __('(no title)')}
|
smallScreenTitle={workflowName || __('(no title)')}
|
||||||
scope={storeName}
|
scope={storeName}
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
import { PanelBody } from '@wordpress/components';
|
import { PanelBody } from '@wordpress/components';
|
||||||
import { useSelect } from '@wordpress/data';
|
import { useSelect } from '@wordpress/data';
|
||||||
import { storeName } from '../../../store';
|
import { store } from '../../../store';
|
||||||
import { StepCard } from '../../step-card';
|
|
||||||
|
|
||||||
export function StepSidebar(): JSX.Element {
|
export function StepSidebar(): JSX.Element {
|
||||||
const { selectedStep, selectedStepType } = useSelect(
|
const { selectedStep } = useSelect(
|
||||||
(select) => ({
|
(select) => ({
|
||||||
selectedStep: select(storeName).getSelectedStep(),
|
selectedStep: select(store).getSelectedStep(),
|
||||||
selectedStepType: select(storeName).getSelectedStepType(),
|
|
||||||
}),
|
}),
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
@ -16,36 +14,20 @@ export function StepSidebar(): JSX.Element {
|
|||||||
return <PanelBody>No step selected.</PanelBody>;
|
return <PanelBody>No step selected.</PanelBody>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!selectedStepType) {
|
|
||||||
return <PanelBody>Unknown step type.</PanelBody>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Edit = selectedStepType.edit;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="block-editor-block-inspector">
|
<PanelBody>
|
||||||
<StepCard
|
<div>
|
||||||
title={selectedStepType.title}
|
<strong>ID:</strong> {selectedStep.id}
|
||||||
description={selectedStepType.description}
|
</div>
|
||||||
icon={selectedStepType.icon}
|
<div>
|
||||||
/>
|
<strong>Type:</strong> {selectedStep.type}
|
||||||
|
</div>
|
||||||
<Edit />
|
<div>
|
||||||
|
<strong>Key:</strong> {selectedStep.key}
|
||||||
<PanelBody title="Debug info" initialOpen={false}>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<strong>ID:</strong> {selectedStep.id}
|
<strong>Args:</strong> {JSON.stringify(selectedStep.args)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
</PanelBody>
|
||||||
<strong>Type:</strong> {selectedStep.type}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<strong>Key:</strong> {selectedStep.key}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<strong>Args:</strong> {JSON.stringify(selectedStep.args)}
|
|
||||||
</div>
|
|
||||||
</PanelBody>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user