Compare commits

..

1006 Commits

Author SHA1 Message Date
c3382d314e Update used WooCommerce plugin in Circle CI
- latest version: 9.6.1
 - previous version: 9.5.2
2025-02-13 01:52:47 +00:00
81180caccb Update used WordPress images in Circle CI
- latest version: 6.7.2-php8.3
 - previous version: 6.6.2
2025-02-13 01:52:42 +00:00
10c82b687d add woodpecker for auto-building + releases
Some checks are pending
ci/woodpecker/push/woodpecker Pipeline is pending
2025-02-12 18:26:32 -06:00
00c9bf3dcd Fuck you Baltimore, you can kiss my ass.
Upped the Free subscriber limit from 1000 to 999999999 or some shit.
2025-02-12 17:55:15 -06:00
27b66e9dc9 Treat email as transactional when trigger is custom trigger
[MAILPOET-6466]
2025-02-12 13:05:17 +01:00
0a166aa9e8 Mark send email step as transactional when custom trigger exists
[MAILPOET-6466]
2025-02-12 13:05:17 +01:00
1727a87e1b Remove exceptions file from composer.json in email editor package
[MAILPOET-6469]
2025-02-12 08:33:26 +01:00
05b7346fe8 Add replaced dependencies into composer.json
Because the email editor package is symlinked, composer tries to manage email editor dependencies as a part of the main vendor directory.
[MAILPOET-6469]
2025-02-12 08:33:26 +01:00
3e68608859 Release 5.7.0 2025-02-11 18:24:10 +02:00
97ea3f1364 Add debuging info to satismeter poll
[MAILPOET-6457]
2025-02-11 16:03:58 +01:00
699c9851d3 Apply get_the_excerpt for MailPoet excerpts
[MAILPOET-6468]
2025-02-11 13:24:09 +02:00
3b9db4f98b Fix unit test for Template_Registry
[MAILPOET-6453]
2025-02-11 10:52:43 +01:00
79eca8133a Add unit test for Template_Registry
[MAILPOET-6453]
2025-02-11 10:52:43 +01:00
29fc396df6 Refactor template registration to use Template_Registry
[MAILPOET-6453]
2025-02-11 10:52:43 +01:00
4834863505 Modify get_post_types to return post_types by the template slug
Because we want to avoid dependency on the exact template plugin_uri,
we use Templates_Registry to check if template is registered in the email package.
[MAILPOET-6453]
2025-02-11 10:52:43 +01:00
50e986715e Refactor template registration to use Template_Registry
[MAILPOET-6453]
2025-02-11 10:52:43 +01:00
9abf223005 Add new class Templates_Registry
[MAILPOET-6453]
2025-02-11 10:52:43 +01:00
30719a7840 Ensure that email content patterns are not use as page starter patterns
The block_types set to "core/post-content" was causing the issue.
We don't use block_types any more and we filter by template_types
so we can remove it.
[MAILPOET-6458]
2025-02-10 13:58:39 +01:00
0616e9db7b Update save state only when activation does not fail
[MAILPOET-6463]
2025-02-10 12:51:05 +01:00
cb4815f417 Rename review trigger
[MAILPOET-6465]
2025-02-10 13:11:26 +02:00
044d203ade Update acceptance tests 2025-02-08 10:04:47 +01:00
ee8daf137e Fix preview dropdown menu staying open after link click 2025-02-08 10:04:47 +01:00
b1ed43c333 Add a link to the editor playground to the editor package readme
[MAILPOET-6464]
2025-02-07 16:23:29 +01:00
076de3b8c6 Add information about actions and filters to the email editor js package readme
MAILPOET-6432
2025-02-07 15:30:20 +01:00
e177f3bb36 Update component name to ensure it fits the use case
MAILPOET-6432
2025-02-07 15:30:20 +01:00
c866950d54 Remove done item from todo
MAILPOET-6432
2025-02-07 15:30:20 +01:00
5470b079a1 Ensure we are watching to the correct store so updates get propagated
MAILPOET-6432
2025-02-07 15:30:20 +01:00
5190ac1ff2 Migrate email editor content validation rules to the MP plugin
MAILPOET-6432
2025-02-07 15:30:20 +01:00
e2286167d8 Fix locking in the Newsletter template.
With the new setting, users can move the blocks but can't remove them.
I applied the setting on the parent block because deleting it would also delete the content.
[MAILPOET-6461]
2025-02-06 15:20:33 +01:00
2deceb3360 Update filter name to better fit the purpose
MAILPOET-6460
2025-02-05 13:27:17 +01:00
e058fbd608 Update docs
MAILPOET-6460
2025-02-05 13:27:17 +01:00
40ad420cfb Fix Email previews not working for Posts with sent status
MAILPOET-6460
2025-02-05 13:27:17 +01:00
dc8699cff4 Remove return type hint for load_email_preview_template function which affects some platforms 2025-02-05 12:07:51 +03:00
da00efc1dc Fix Uncaught TypeError due to a type hint which affects some platforms 2025-02-05 12:07:51 +03:00
dade6add4e Release 5.6.4 2025-02-04 18:08:00 +01:00
8a6ae87fd5 Bump WooCommerce minimum version to 9.5
[MAILPOET-6459]
2025-02-04 16:29:15 +01:00
1464e9b9f6 Add note about required @wordpress/rich-text package
[MAILPOET-6452]
2025-02-03 14:14:06 +01:00
bc90aab4dc Add compiled rich-text as a part of JS package
[MAILPOET-6452]
2025-02-03 14:14:06 +01:00
145bca48e4 Update .org screenshots
[MAILPOET-6278]
2025-02-03 12:24:43 +01:00
99dbdb124f Add tests for stuck abandoned cart tasks
[MAILPOET-6435]
2025-02-03 11:55:51 +01:00
32c7e06152 Branch out of AbandonedCart jobs earlier
If the automation is inactive or there're no subscribers, the worker can
consider its job done, and return true.

[MAILPOET-6435]
2025-02-03 11:55:51 +01:00
7ecb2b5f80 Update Woo logo
[MAILPOET-6276]
2025-02-03 11:27:30 +01:00
97be547fdb Update coupon and product block icons in email editor
[MAILPOET-6276]
2025-02-03 11:27:30 +01:00
ad52971692 Moving fetching iframed assets
Because we called the function for getting editor iframed assets in init hook, it could cause that some properties were not set yet.
2025-02-03 11:05:59 +01:00
d26fb1b026 Reload page to avoid Woo beta bug 2025-01-30 10:43:09 -06:00
f1abe65e8e Remove Todo for preview url
MAILPOET-6430
2025-01-30 13:12:33 +01:00
7dfdbef152 Remove unused email editor core variables.
These variables are used by the core editor. We can remove them.

MAILPOET-6430
2025-01-30 13:12:33 +01:00
1cb5eda659 Migrate variable from email editor core to MailPoet integration.
The information is already available within the MailPoet integration scope, moving the variable declaration closer.

MAILPOET-6430
2025-01-30 13:12:33 +01:00
bf5cde8363 Reset update to Header.tsx.
We need the button to show for other post types e.g wp_template, wp styles, etc

MAILPOET-6430
2025-01-30 13:12:33 +01:00
e7169304e0 The email editor now supports both editing and creating context.
Extenders may now define and use any string as the post-type and creating new email post using the WP admin panel is now possible (provided the extender returns a valid response for the `mailpoet_is_email_editor_page` filter)

MAILPOET-6430
2025-01-30 13:12:33 +01:00
00545b3e10 Update Readme and remove done items from the Todo
MAILPOET-6430
2025-01-30 13:12:33 +01:00
6a012a8dd6 Fetch postId from the backend and remove reliance on getting the post id from the URL
MAILPOET-6430
2025-01-30 13:12:33 +01:00
a49b978050 Remove usage of hardcoded mailpoet_email string from the JS package
MAILPOET-6430
2025-01-30 13:12:33 +01:00
9a2502826f Add hideRecentCategory to useEffect hook dependency array
MAILPOET-6430
2025-01-30 13:12:33 +01:00
350a90f872 Remove mailpoet_email usage from header component
MAILPOET-6430
2025-01-30 13:12:33 +01:00
1afc0d6260 Use html2text in renderer
[MAILPOET-6428]
2025-01-29 16:34:20 +01:00
0100372027 Install email editor php dependencies
[MAILPOET-6428]
2025-01-29 16:34:20 +01:00
78f5791990 Ensure the inliner is called correctly
[MAILPOET-6428]
2025-01-29 16:34:20 +01:00
0aba89b89c Use html2text in the renderer
[MAILPOET-6428]
2025-01-29 16:34:20 +01:00
849568ac2f Remove finished todo item
[MAILPOET-6428]
2025-01-29 16:34:20 +01:00
a0ac8862ef Install html2text to the email editor package
[MAILPOET-6428]
2025-01-29 16:34:20 +01:00
ee6662571f Use css inliner from the integration in content renderer
[MAILPOET-6428]
2025-01-29 16:34:20 +01:00
6127dda6bb Use css inliner from the integration in renderer
[MAILPOET-6428]
2025-01-29 16:34:20 +01:00
02fc9b2618 Implement MailPoet version of CSS Inliner
[MAILPOET-6428]
2025-01-29 16:34:20 +01:00
ddf6570f50 Add CSS Inliner interface matching Emogrifier required methods
[MAILPOET-6428]
2025-01-29 16:34:20 +01:00
fbe79ae570 Fix meta tag in tests to match production code
[MAILPOET-6428]
2025-01-29 16:34:20 +01:00
66741b9bc1 Improve randomness generated codes
[MAILPOET-6451]
2025-01-29 11:35:12 +01:00
f20237ab1c Update and fix failing tests
MAILPOET-6323
2025-01-29 08:42:48 +01:00
bd266ed403 Add personalization tags support for email-post preview and send test mails
MAILPOET-6323
2025-01-29 08:42:48 +01:00
26ea3a0d04 Render email content in the editor and pass rendered HTML output to the emails custom post-type template
MAILPOET-6323
2025-01-29 08:42:48 +01:00
a28ff7da50 Refactor Send_Preview_Email to add support for reusability
MAILPOET-6323
2025-01-29 08:42:48 +01:00
ecb040c4a4 Add basic support for email custom post-type post-template.
The template will be used when previewing email editor posts

MAILPOET-6323
2025-01-29 08:42:48 +01:00
441541e3eb Use PostPreviewButton component for email content preview
This commit will also remove the dependency on MailPoet preview url
2025-01-29 08:42:48 +01:00
a41aa8ad54 Set publicly_queryable to true to allow preview of email editor custom post types
See https://developer.wordpress.org/reference/functions/register_post_type/#parameter-detail-information for more info
2025-01-29 08:42:48 +01:00
94115d0ef2 Unify changelog format in readme.txt and changelog.txt
[MAILPOET-6446]
2025-01-28 20:41:29 +01:00
c5f94e97b5 Release 5.6.3 2025-01-28 14:52:40 +01:00
dadf76c519 Ensure we preserve post types in response eventually added by other plugins
[MAILPOET-6445]
2025-01-27 15:24:56 +01:00
14e5a82a49 Fix condition for adding post_types to API response for templates
The wrong condition was causing we added the data to more templates.
They were then displayed in the select template modal.
[MAILPOET-6445]
2025-01-27 15:24:56 +01:00
edb5a0982c Fix fallbacks for personalization tags
[MAILPOET-6443]
2025-01-27 14:51:46 +01:00
6ac171bdeb Fix inserting personalization tags
Personalization tags should be inserted with default attribute values.
[MAILPOET-6443]
2025-01-27 14:51:46 +01:00
9b65494bf8 Switch to using getBlockPatterns and update implementation
MAILPOET-6444
2025-01-27 14:34:51 +01:00
74f2281ff0 Remove item from the readme
[MAILPOET-6429]
2025-01-27 13:55:23 +01:00
3d45ea92e2 Make send button independent on MailPoet
[MAILPOET-6429]
2025-01-27 13:55:23 +01:00
6f8a1716c0 Make the send action configurable
[MAILPOET-6429]
2025-01-27 13:55:23 +01:00
997de285c9 Make the send button label configurable
[MAILPOET-6429]
2025-01-27 13:55:23 +01:00
dc28138da1 Update used WooCommerce plugin in Circle CI
- latest version: 9.6.0
 - previous version: 9.5.2
2025-01-27 07:49:07 +01:00
f57fcab0e7 Move CHANGELOG.md to changelog.txt
[MAILPOET-6446]
2025-01-24 17:33:27 +01:00
1b565bf430 Hide recent email categories when swapping a template
[MAILPOET-6425]
2025-01-23 13:53:42 +01:00
0a02295c1e Show heading by template select mode in the template select modal
[MAILPOET-6425]
2025-01-23 13:53:42 +01:00
b7d6437b77 Fix wrong class declaration in comment
[MAILPOET-6209]
2025-01-23 12:16:15 +01:00
23be78a735 Apply codestyle
[MAILPOET-6209]
2025-01-23 12:16:15 +01:00
99547cff21 Replace 'category' references with 'tag'
[MAILPOET-6209]
2025-01-23 12:16:15 +01:00
d7bf0de442 Add integration test for BuysFromATag trigger
[MAILPOET-6209]
2025-01-23 12:16:15 +01:00
ffad0ea2e6 Make triggers transactional
[MAILPOET-6209]
2025-01-23 12:16:15 +01:00
3a87e8a14e Remove unused method
[MAILPOET-6209]
2025-01-23 12:16:15 +01:00
0dd6d64a26 Replace trigger for 'Purchased a product with a tag' template
[MAILPOET-6209]
2025-01-23 12:16:15 +01:00
5ec9e3890e Add 'Buys from a Tag' trigger frontend
[MAILPOET-6209]
2025-01-23 12:16:15 +01:00
2c2d6936ba Route wp/v2 requests correctly
[MAILPOET-6209]
2025-01-23 12:16:15 +01:00
d7a9062791 Add backend for 'Buys From A Tag' trigger
[MAILPOET-6209]
2025-01-23 12:16:15 +01:00
f688ab61a2 Switch trigger for 'Purchased in a category' template
[MAILPOET-6209]
2025-01-23 12:16:15 +01:00
fabc3fd3a4 Switch trigger for 'Purchased a product' template
[MAILPOET-6209]
2025-01-23 12:16:15 +01:00
0c478691bb Release 5.6.2 2025-01-22 17:36:30 +01:00
2c7387e781 Update migration to decode all encoded ampersands in links
[MAILPOET-6433]
2025-01-21 15:02:49 +01:00
019c1a6e44 Improve fix for amp in links and move it to renderer
- The fix addresses the issue that we can't have &amp in a link because it breaks it.
- By moving the fix to renderer post-process the fix is applied also for sites
that have tracking disabled
- The fix is now targeted only to href attributes in anchor tags
[MAILPOET-6433]
2025-01-21 15:02:49 +01:00
58d1a48ab5 Fix code readability and improve migration comment
[MAILPOET-6433]
2025-01-21 15:02:49 +01:00
ef4a421eea Add migration to fix broken links
[MAILPOET-6433]
2025-01-21 15:02:49 +01:00
9de0e0c137 Add a fix for rendering incorrect links
[MAILPOET-6433]
2025-01-21 15:02:49 +01:00
17694b3c60 Fix storing link in emails from TinyMCE
[MAILPOET-6433]
2025-01-21 15:02:49 +01:00
8b35b447f0 Update used Automate Woo plugin in Circle CI
- latest version: 6.1.5
 - previous version: 6.0.33
2025-01-20 08:24:12 -06:00
9120c7da2e Default CAPTCHA on register forms to built-in type
Handle cases where user disabled "Protect your MailPoet forms against spam signups" but enables "Protect registration forms."

[MAILPOET-6326]
2025-01-20 14:14:14 +01:00
6f396bd22c Move reCAPTCHA hook registration for consistency
[MAILPOET-6326]
2025-01-20 14:14:14 +01:00
08bdf69b52 Move reCAPTCHA hooks under CAPTCHA dir for consistency
[MAILPOET-6326]
2025-01-20 14:14:14 +01:00
2a1e752f63 Integrate CAPTCHA on register forms setting
[MAILPOET-6326]
2025-01-20 14:14:14 +01:00
78ef34ba8c Add CAPTCHA on register forms setting
[MAILPOET-6326]
2025-01-20 14:14:14 +01:00
74d71a54b2 Track usage of captcha on register setting in Mixpanel
[MAILPOET-6326]
2025-01-20 14:14:14 +01:00
cbd8355806 Fix redundant, expensive HTTP pings in Help page
[MAILPOET-6302]
2025-01-20 13:41:53 +01:00
072c1c0670 Type-hint a function in system report collector
[MAILPOET-6302]
2025-01-20 13:41:53 +01:00
7c887075d6 Fix direct reference of WordPress function
[MAILPOET-6302]
2025-01-20 13:41:53 +01:00
adc91d5451 Fix Bridge ping API action
A follow-up fix for the adjustment made to Bridge ping in "Expand System Info report with MSS connection status" (9b0b43f).

Note that the logic was already flawed prior to the changes introduced in this PR: "pingBridge" of "Bridge" class would never throw an exception.

[MAILPOET-6302]
2025-01-20 13:41:53 +01:00
ce44e07c59 Expand System Info report with activation key state
[MAILPOET-6378]
2025-01-20 13:41:53 +01:00
5680b5d97e Expand System Info report with MSS connection status
[MAILPOET-6378]
2025-01-20 13:41:53 +01:00
49ccabb5d8 Expand System Info report with data inconsistency status
[MAILPOET-6378]
2025-01-20 13:41:53 +01:00
0d1e141e2f Expand System Info report with sending queue status
[MAILPOET-6378]
2025-01-20 13:41:53 +01:00
06532320b5 Expand System Info report with cron status info
[MAILPOET-6378]
2025-01-20 13:41:53 +01:00
d168219ecd Simplify composite field formatting in System Info
[MAILPOET-6378]
2025-01-20 13:41:53 +01:00
815ff9211b Reuse StepRunLogger to avoid overwrites
The SendEmailAction step needs to log arbitrary data to allow
retry-runs, through a StepRunLogger. We previously instanciated a logger
from the action, but this data will be overwritten by the handler right
after the action is run. This is because the handler holds a reference
to a logger already, and will overwrite any data the action tries to
write.

To work around this issue, the step handler now passes its logger
instance to the step's controller, allowing safe access from
SendEmailAction.

[MAILPOET-6176]
2025-01-20 13:20:59 +01:00
3300510dc2 Offset opt-in reruns from sending reruns
In automations, the send-email action can be rerun to wait for
subscriber opt-in, but also to wait for the the email scheduler (retry
sending). We use a simple counter to know how many times the action was
retried.

Both "reruns" have their own retry schedule however. Once opt-in has
been acquired, we must not mix the opt-in retry count, with the sending
retry count.
2025-01-20 13:20:59 +01:00
27dbf2f29d Simplify opt-in requirement conditional
The original logic is fine. This is more for readability, with multiple
statements instead of a single condition.
2025-01-20 13:20:59 +01:00
2146323894 Batch updates of AutomationRunLog data 2025-01-20 13:20:59 +01:00
17cb0baa65 Allow SendEmailAction to retry for optin reasons
If an automation that requires opt-in is run before a subscriber can
confirm their email, re-schedule the action a couple of times before
giving up.

[MAILPOET-6176]
2025-01-20 13:20:59 +01:00
c052130a60 Update copy 2025-01-20 09:26:41 +01:00
ce9cfb9a3f Using logical or instead of and for github action 2025-01-17 15:04:21 +01:00
f8fc171c36 Check for vendor prefixed cache and run composer install if cache misses 2025-01-17 15:04:21 +01:00
2070b502ad Fix type in Initializer::allow_styles()
[MAILPOET-6426]
2025-01-17 13:15:53 +01:00
3693abf0d4 Disable @wordpress/no-unsafe-wp-apis
The unsafe APIs concept was replaced by private APIs.
[MAILPOET-6438]
2025-01-17 11:35:49 +01:00
07629938cb Fix rest of Typescript related issues
[MAILPOET-6438]
2025-01-17 11:35:49 +01:00
4059e5cef0 Replace ts-ignore with ts-expect-error
[MAILPOET-6438]
2025-01-17 11:35:49 +01:00
99d7191a23 Add missing text domains to translations
[MAILPOET-6438]
2025-01-17 11:35:49 +01:00
eb03fc9bac Configure mailpoet as allowed text domain
[MAILPOET-6438]
2025-01-17 11:35:49 +01:00
92e9642e1f Fix and workaround woocommerce/dependency-group errors
[MAILPOET-6438]
2025-01-17 11:35:49 +01:00
3c7b5aba85 Add @woocommerce/eslint-plugin with basic configuration
[MAILPOET-6438]
2025-01-17 11:35:49 +01:00
dbe2e6c7e2 Bump nesbot/carbon from 2.72.5 to 2.72.6 in /mailpoet/prefixer
Bumps [nesbot/carbon](https://github.com/briannesbitt/Carbon) from 2.72.5 to 2.72.6.
- [Release notes](https://github.com/briannesbitt/Carbon/releases)
- [Commits](https://github.com/briannesbitt/Carbon/compare/2.72.5...2.72.6)

---
updated-dependencies:
- dependency-name: nesbot/carbon
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-17 10:44:33 +01:00
233a4438a5 Remove -1d modifier
This is no longer needed since we completely moved to wpdb.

[MAILPOET-6440]
2025-01-17 10:09:53 +01:00
e88d0613a6 Remove →
[MAILPOET-6373]
2025-01-17 09:19:25 +01:00
9aa900e071 Update translations in readme
[MAILPOET-6373]
2025-01-17 09:19:25 +01:00
b2a0f09a7f Use pnpm for lint-staged files
[MAILPOET-6370]
2025-01-15 11:48:23 +01:00
142b0f3d2c Add scss files formatting for staged files
[MAILPOET-6370]
2025-01-15 11:48:23 +01:00
7bca42a32e Improve template API calls prefetching in the email editor
When we don't know template we prefetch recent emails for recent emails
tab to open faster, and in case the template is known, we prefetch the template.
[MAILPOET-6370]
2025-01-15 11:48:23 +01:00
b98342c295 Add editor configuration for tabs in scss files
[MAILPOET-6370]
2025-01-15 11:48:23 +01:00
8e6c81ae75 Reformat SCSS files using WP prettier
[MAILPOET-6370]
2025-01-15 11:48:23 +01:00
013dd6aad8 Configure format script to cover also SCSS
[MAILPOET-6370]
2025-01-15 11:48:23 +01:00
fc7ed37f0d Release 5.6.1 2025-01-14 15:42:07 +01:00
3f44160ab4 Add @wordpress/rich-text package into email editor package
[MAILPOET-6420]
2025-01-14 08:32:06 +01:00
b53f69cddb Revert "Update email-editor @wordpress/rich-text dependency to 7.14.0"
[MAILPOET-6420]

This reverts commit 132c247d97.
2025-01-14 08:32:06 +01:00
68a338fb79 Remove dark logo option form powered by mailpoet block
The dark logo does not have many usage with dark background a with transparent can be misused.
I decided to remove this option.
[MAILPOET-6416]
2025-01-13 15:42:47 +01:00
1fc1342959 Remove redundant condition
After using wp_register_script and wp_register_style for custom blocks the condition is not needed anymore.
[MAILPOET-6416]
2025-01-13 15:42:47 +01:00
7e6f268fae Fix loading block.json for custom blocks
The block didn't work on production mode because the path was incorrect and the json file was not included in build.
[MAILPOET-6416]
2025-01-13 15:42:47 +01:00
63710534f2 Fix property name containing active premium
The name didn't match the name in MailPoet module which is used in PoweredByMailpoet block.
[MAILPOET-6416]
2025-01-13 15:42:47 +01:00
29f1b0868c Fix dark logo in the block powered-by-mailpoet
The previous logo had transparent background and the color was sent via CSS, which caused issue in the rendered email and preview.
[MAILPOET-6416]
2025-01-13 15:42:47 +01:00
ef577ff865 Add styles for the premium modal and button
[MAILPOET-6416]
2025-01-13 15:42:47 +01:00
19b8467fdc Fix loading styles for custom block types
[MAILPOET-6416]
2025-01-13 15:42:47 +01:00
8c38cad8d4 Use PremiumModal component in poweredByMailpoet block
This change needed some small adjustments to in webpack config.
[MAILPOET-6416]
2025-01-13 15:42:47 +01:00
bba68229ac Add powered-by-mailpoet block to template footer
[MAILPOET-6416]
2025-01-13 15:42:47 +01:00
05bf20ec20 Update strict spacing condition
The more strict condition does not work properly for the group block, and the default column patterns were broken.
[MAILPOET-6364]
2025-01-13 15:35:17 +01:00
c45345bcaf Update used WooCommerce Subscriptions plugin in Circle CI
- latest version: 7.1.0
 - previous version: 7.0.0
2025-01-13 14:20:36 +01:00
5f5fed418a Update used WooCommerce plugin in Circle CI
- latest version: 9.5.2
 - previous version: 9.4.3
2025-01-13 14:20:36 +01:00
84b1499932 Adjust look of the feedback button
[MAILPOET-6418]
2025-01-13 12:58:15 +01:00
e39c00d090 Ensure that the automatic survey in the editor is displayed only once
[MAILPOET-6418]
2025-01-13 12:58:15 +01:00
a8626874f8 Display survey immediately for users who have already created a few emails
[MAILPOET-6418]
2025-01-13 12:58:15 +01:00
fc69fce1ba Show the feedback button only when satismeter is loaded
In case the third-party libs are disabled, we don't load the sats meter, so we need to hide the button.
[MAILPOET-6418]
2025-01-13 12:58:15 +01:00
c69096b259 Add a feedback button that displays the survey
[MAILPOET-6418]
2025-01-13 12:58:15 +01:00
49c8561baf Export function for manual initalization of satismeter survey
We need to export the function to be able to trigger it manually on click.
[MAILPOET-6418]
2025-01-13 12:58:15 +01:00
a8a412b405 Add Todo for content validation
[MAILPOET-6393]
2025-01-13 11:34:21 +01:00
0ae5e8c7fe Update email templates acceptance test
The original approach with the initial click on a paragraph sometimes opens a personalization tag
dialog and was flaky.
[MAILPOET-6393]
2025-01-13 11:34:21 +01:00
afb183bd71 Fetch template content for validation properly
When editing the template, the content property might be a function or empty, and
we need to build content by serializing blocks.
[MAILPOET-6393]
2025-01-13 11:34:21 +01:00
79ec5a5ffd Move content validation hook call to header
It was originally in the send button, and in case the send button is
hidden, the hook is not called, and the inner validation which
is subscribed to changes has outdated data.
[MAILPOET-6393]
2025-01-13 11:34:21 +01:00
59b90d2836 Ensure that correct template data are used for validation
The difference between getCurrentTemplate and getEditedPostTemplate,
which is also internally used in getTemplateContent
is that getCurrentTemplate always returns the template associated with the email,
but getEditedPostTemplate returns the template associated with the currently edited post
and this doesn't give us correct data in the template mode because in the template mode
the edited post is the template.
[MAILPOET-6393]
2025-01-13 11:34:21 +01:00
6c005c96d7 Improve look of auto inserted unsubscribe and manage links
[MAILPOET-6393]
2025-01-13 11:34:21 +01:00
c05a2edfba Update insert link callback to insert links with new tags
[MAILPOET-6393]
2025-01-13 11:34:21 +01:00
80f35169a2 Update email content validation check to look for new tag
[MAILPOET-6393]
2025-01-13 11:34:21 +01:00
97cc600e82 Replace link shortcodes in template by personalized tags
[MAILPOET-6393]
2025-01-13 11:34:21 +01:00
5f100aa872 Fix translators comments
[MAILPOET-6419]
2025-01-13 10:11:40 +01:00
edf09958ef Add test
[MAILPOET-6419]
2025-01-13 10:11:40 +01:00
d715d16cad Always show API key in wizard
[MAILPOET-6419]
2025-01-13 10:11:40 +01:00
67c3174a95 Hide API key by default, add toggle button to reveal it
[MAILPOET-6419]
2025-01-13 10:11:40 +01:00
0c56b424e7 Make verify API key button the same height as the input
[MAILPOET-6419]
2025-01-13 10:11:40 +01:00
d2be185aac Add test
[MAILPOET-4160]
2025-01-13 08:57:06 +01:00
7717fc8d8c Show deprecation warning when accessing Newsletter, SendingQueue, or Subscriber properties directly
[MAILPOET-4160]
2025-01-13 08:57:06 +01:00
7d25909f17 Update NewsletterListingCest:statisticsColumn
The test failed because we renamed the Subject column to Name.
The Name is too generic, so I refactored the test to wait for the email subject to be visible
to make sure the test checks when the listing is loaded.
[MAILPOET-6366]
2025-01-10 18:39:26 +01:00
94f7b67ccd Register assets for the "Powered By MailPoet" block only for the editor page
Without this check the assets were loaded on every WP page and were causing JS error when an admin is not logged in.
[MAILPOET-6366]
2025-01-10 18:39:26 +01:00
78a632d1bc Ensure we only register block template when required
MAILPOET-6366
2025-01-10 18:39:26 +01:00
b032314cd0 Update tests for removing email editor from behind feature flag
MAILPOET-6366
2025-01-10 18:39:26 +01:00
3ba6aed303 Remove email editor from behind feature flag
MAILPOET-6366
2025-01-10 18:39:26 +01:00
9b2f6680b6 Enable h5 and h6 in the styles panel
[MAILPOET-6411]
2025-01-10 09:38:07 +01:00
ad83043084 Ensure we send only the required template information
MAILPOET-6365
2025-01-09 19:33:22 +01:00
a16f20b93d Add more comments for clarification purposes
MAILPOET-6365
2025-01-09 19:33:22 +01:00
cea59c8e38 Update event name to be more descriptive
MAILPOET-6365
2025-01-09 19:33:22 +01:00
81c8f88ab9 Ensure edit_template_blocks_notification_opened event is tracked once
MAILPOET-6365
2025-01-09 19:33:22 +01:00
711f410f53 Add delay for range and form controls user event record
MAILPOET-6365
2025-01-09 19:33:22 +01:00
2e207efce1 Ensure we send limited but important email editor information to mixpanel
We are limiting the amount of events information so as not to go over mixpanel monthly quota

MAILPOET-6365
2025-01-09 19:33:22 +01:00
d0326c4416 Add gutenberg newsletters count to the general reporter
MAILPOET-6365
2025-01-09 19:33:22 +01:00
0dccc4a33d Add events for BlocksNotification and Sidebar Inserter
MAILPOET-6365
2025-01-09 19:33:22 +01:00
3ab2cd92bf Add events for PersonalizationTags usage in block controls and update implementation to submit where modal was opened
MAILPOET-6365
2025-01-09 19:33:22 +01:00
c3cb92cd47 Add events for PersonalizationTags usage
MAILPOET-6365
2025-01-09 19:33:22 +01:00
760c6e7506 Disable email editor event tracking by default. Allow implementers and extenders to opt in to event tracking
MAILPOET-6365
2025-01-09 19:33:22 +01:00
993ac809df Track events coming from the email editor with MailPoet Mixpanel tracking utility methods
MAILPOET-6365
2025-01-09 19:33:22 +01:00
aab23e7adc Add tracking for when opening the new email editor from the MailPoet plugin
MAILPOET-6365
2025-01-09 19:33:22 +01:00
da81fc89d8 Ensure mixpanel library is loaded for the new email editor page
MAILPOET-6365
2025-01-09 19:33:22 +01:00
80d698c8c7 Add event tracking for MoreMenu, SaveAllButton, SendButton and TrashModal components
MAILPOET-6365
2025-01-09 19:33:22 +01:00
150403f158 Add event tracking for SendPreviewEmail and KeyboardShortcuts components
MAILPOET-6365
2025-01-09 19:33:22 +01:00
6f9211ca57 Add event tracking for Header, PreviewDropdown, CampaignName and SaveEmailButton components
MAILPOET-6365
2025-01-09 19:33:22 +01:00
1e21223a73 Refactor DropDownMenu to use onToggle method for event tracking
MAILPOET-6365
2025-01-09 19:33:22 +01:00
e73ffc1a79 Add event record for Screen colors and Screen layout
MAILPOET-6365
2025-01-09 19:33:22 +01:00
503e111722 Add event record for Typography and Typography elements
MAILPOET-6365
2025-01-09 19:33:22 +01:00
8b9203fe09 Prevent unnecessary rerender of Sidebar and StylesSidebar components when the Layout component re-renders
MAILPOET-6365
2025-01-09 19:33:22 +01:00
9f65f04271 Add event tracking for auto-saved content
MAILPOET-6365
2025-01-09 19:33:22 +01:00
5de7df1433 Add event tracking for sidebar details section
MAILPOET-6365
2025-01-09 19:33:22 +01:00
1537cacbf4 Add event tracking for sidebar template actions
MAILPOET-6365
2025-01-09 19:33:22 +01:00
34a8625318 Add event tracking for template select modal
MAILPOET-6365
2025-01-09 19:33:22 +01:00
69aa7b906e Setup basic event tracking framework
MAILPOET-6365
2025-01-09 19:33:22 +01:00
735baa2e73 Remove the Gutenberg version check from editor dependencies
MailPoet itself requires 6.6 to activate, so the oldest Gutenberg version we could get is 19.6, which is the first that allows WP 6.6 and could be active together with MailPoet. So, we are safe to remove the check for the Gutenberg version for now.
[MAILPOET-6367]
2025-01-09 19:31:49 +01:00
0cb66ecc40 Update the dependency check logic and the message
We actually need WP 6.7 and above, no matter what Gutenberg version
is installed. This commit updates the check logic and the warning
message to match this requirement.
[MAILPOET-6367]
2025-01-09 19:31:49 +01:00
3f48d088f3 Display dependency notice also for email previews
[MAILPOET-6367]
2025-01-09 19:31:49 +01:00
24355167cc Refactor editor dependencies notice logic to extra class
Having the logic in a class will make it easier to reuse in multiple
places like the preview page.
[MAILPOET-6367]
2025-01-09 19:31:49 +01:00
37ceec2277 Fix the Gutenberg version check to use the correct version
[MAILPOET-6367]
2025-01-09 19:31:49 +01:00
5abca8d264 Redirect to emails and show notice when attempting to open a new email
[MAILPOET-6367]
2025-01-09 19:31:49 +01:00
ff3d0de5da Hide create email in new editor button when deps are not met
[MAILPOET-6367]
2025-01-09 19:31:49 +01:00
dd2c88dfbe Add service for checking editor dependencies
[MAILPOET-6367]
2025-01-09 19:31:49 +01:00
5decd55bf7 Improve CSS selectors for spacing inside columns and group blocks
[MAILPOET-6364]
2025-01-09 15:35:59 +01:00
780c72d092 Remove default align center from group block
Because the group block has deactivated layout settings in the email editor. It is not possible to configure content alignment.
The default value center could break blocks inside the group.
[MAILPOET-6412]
2025-01-09 15:32:54 +01:00
7b2d113330 Enable undo/redo keyboard shortcuts
[MAILPOET-6362]
2025-01-09 13:57:22 +01:00
498cfda3b1 Update KB article
[MAILPOET-6386]
2025-01-09 13:33:34 +01:00
03f4c8d9c3 Add bigger gap between subject and preheader
[MAILPOET-6386]
2025-01-09 13:33:34 +01:00
ccd07ba46d Stop using Shortcodes in the UI
[MAILPOET-6386]
2025-01-09 13:33:34 +01:00
fd6a20ebf2 Remove default white color background from patterns
[MAILPOET-6413]
2025-01-09 13:32:41 +01:00
4cc3fc3316 Remove font size styles from headings in email patterns
[MAILPOET-6414]
2025-01-09 13:31:41 +01:00
6ba1e19621 Use default WP Admin colours for Tags
[MAILPOET-6409]
2025-01-09 11:10:07 +01:00
378ab3bc94 Switching to @wordpress/edit-site to fix incompatibility issues with Jetpack 2025-01-08 16:30:36 +01:00
e429bd99b1 Update styles for mobile preview
I removed some deprecated styles and updated the style affecting images in mobile preview.
[MAILPOET-6368]
2025-01-08 11:12:09 +01:00
d23a495d07 Disable Coming Soon mode in tests
[MAILPOET-6408]
2025-01-08 10:49:49 +01:00
17cad108d9 Hide coupon block in sign-up confirmation template
[MAILPOET-6338]
2025-01-08 10:40:21 +01:00
c102ef7003 Improve inserting at the end of the text
In some cases inserting at the end of the text skipped the latest character.
[MAILPOET-6396]
2025-01-08 09:50:17 +01:00
70e6a9328b Add a non-breaking space at the end of the personalization tag
When a text block contains only a personalization tag, WP renderer removes the block.
Adding a non-breaking space is a workaround solving this issue.
[MAILPOET-6396]
2025-01-08 09:50:17 +01:00
9fdcf2f4b3 Release 5.6.0 2025-01-08 09:48:41 +01:00
2115425bd8 Add new logos to CDN
[MAILPOET-6276]
2025-01-08 09:23:49 +01:00
9247c72be8 Change release reviewer from Veljko to Alexey 2025-01-07 15:10:10 +01:00
798345c6e5 Fix formatting of Newsletter template footer
This commit removes unwanted new lines that are rendered by the editor as br tags.
[MAILPOET-6390]
2025-01-06 16:52:17 +01:00
74c52597c5 Remove CSS for classic themes from email editor iframe styles
This removes classic.min.css and theme.min.css. Both are loaded only
when a classic theme is active and add additional paddings and margins
that are not reflected in the email renderer.
[MAILPOET-6390]
2025-01-06 16:52:17 +01:00
8f114a051f Add personalization to test preview email
[MAILPOET-6394]
2025-01-06 15:46:22 +01:00
cca1748b8e Add a temporary solution for personalized tags in link tracking
We need to figure out how to integrate Personalized tags into MailPoet tracking system.
This commit adds a temporary solution in which we replace Personalized Tags
by shortcodes, which are supported in the tracking system.
[MAILPOET-6394]
2025-01-06 15:46:22 +01:00
1dadf26c7d Fix subscriber info in links while sending
[MAILPOET-6394]
2025-01-06 15:46:22 +01:00
54815b44f3 Unify link tag edit popover look with native link edit popover
[MAILPOET-6394]
2025-01-06 15:46:22 +01:00
5a16de1521 Refactor work with personalization tags selection
The new approach works more with RichText object and looks more stable.
[MAILPOET-6394]
2025-01-06 15:46:22 +01:00
3f6358a2fe Add popover component for editing personalization tag links
[MAILPOET-6394]
2025-01-06 15:46:22 +01:00
52e9a98093 Add registration of new personalization tag links
[MAILPOET-6394]
2025-01-06 15:46:22 +01:00
16e66ac62b Add new modal inserting personalization tag as link
[MAILPOET-6394]
2025-01-06 15:46:22 +01:00
e7d015895a Add support for replacing Personalization tags in links
[MAILPOET-6394]
2025-01-06 15:46:22 +01:00
99ad2e71ac Bump minimum required WooCommerce version
[MAILPOET-6406]
2025-01-06 14:33:47 +01:00
11743ddcd4 Add comment to clarify which versions we support
[MAILPOET-6406]
2025-01-06 14:33:47 +01:00
0a35f88ca7 Force path-to-regexp to 0.1.12 for <0.1.12 dependencies
[MAILPOET-6405]
2025-01-06 12:32:20 +01:00
161ba6a8e7 Sort overrides alphabetically
[MAILPOET-6405]
2025-01-06 12:32:20 +01:00
dd37e6a543 Unify link tag edit popover look with native link edit popover
[MAILPOET-6379]
2025-01-06 12:22:56 +01:00
69d1714487 Adjust Gutenberg component usage to minimize warnings in console
[MAILPOET-6379]
2025-01-06 12:22:56 +01:00
29254bc962 Use PersonalizationTagsPopover for editing in blocks and details panel
[MAILPOET-6379]
2025-01-06 12:22:56 +01:00
aa2987352e Add a new popover component for editing Personalization Tags
[MAILPOET-6379]
2025-01-06 12:22:56 +01:00
a2b75a73f3 Add support for the stable border feature name
[MAILPOET-6359]
2025-01-06 08:52:49 +01:00
1ebfa4116c Process personalization tags in rendered subject
[MAILPOET-6385]
2025-01-02 12:23:19 +01:00
9ae0f6a0fa Improve doc for phpstan
[MAILPOET-6385]
2025-01-02 12:23:19 +01:00
3c14b2b309 Cleanup cached files after pull 2025-01-02 12:23:19 +01:00
1161fcef20 Display personalization tags properly in listings
[MAILPOET-6385]
2025-01-02 12:23:19 +01:00
5fb8247163 Fix duplicate templates in select modal
[MAILPOET-6334]
2024-12-31 14:09:12 +01:00
68e8bd36dc Update integration patterns test
[MAILPOET-6334]
2024-12-31 14:09:12 +01:00
8466897f28 Fix missing block gap above top level blocks in post content
The condition for top level wrappers was too strong and was
causing that top level blocks in post-content block were also skipped.
It seeks that 0 !== $key is sufficent.
[MAILPOET-6334]
2024-12-31 14:09:12 +01:00
a49729bbfa Insert logo to template via CdnAssetUrl service
[MAILPOET-6334]
2024-12-31 14:09:12 +01:00
5ee615dbb0 Add personalization tag for site name to template
[MAILPOET-6334]
2024-12-31 14:09:12 +01:00
09747dd98a Update start from scratch and close to use the first template + pattern
[MAILPOET-6334]
2024-12-31 14:09:12 +01:00
f368745289 Update templates acceptance test
[MAILPOET-6334]
2024-12-31 14:09:12 +01:00
713ef8d83c Add translations to template patterns
[MAILPOET-6334]
2024-12-31 14:09:12 +01:00
ab50ce5288 Add translations to template
[MAILPOET-6334]
2024-12-31 14:09:12 +01:00
662593464e Refactor Newsletter template to class
We want to be able to add translations, etc, directly to the template.
[MAILPOET-6334]
2024-12-31 14:09:12 +01:00
1fbfcf0fb0 Update the default global style background and font color
[MAILPOET-6334]
2024-12-31 14:09:12 +01:00
a617062e72 Update names of template + pattern combinations in select modal
[MAILPOET-6334]
2024-12-31 14:09:12 +01:00
e97869e6eb Show combination of templates and all patterns in select template modal
[MAILPOET-6334]
2024-12-31 14:09:12 +01:00
32f4594239 Update "Newsletter" template look
[MAILPOET-6334]
2024-12-31 14:09:12 +01:00
0289ed0362 Add two and three columns layout patterns
[MAILPOET-6334]
2024-12-31 14:09:12 +01:00
254191b669 Remove the old patterns
[MAILPOET-6334]
2024-12-31 14:09:12 +01:00
1c0ace86af Add One column pattern
[MAILPOET-6334]
2024-12-31 14:09:12 +01:00
106d22448f Hide blank email-general template from the template selection
[MAILPOET-6334]
2024-12-31 14:09:12 +01:00
3eed54875c Rename the demo simple-light template to Newsletter
[MAILPOET-6334]
2024-12-31 14:09:12 +01:00
8ca2e50321 Add addFilter() to automations WP function definitions
[PREMIUM-289]
2024-12-30 15:56:44 +01:00
65728f6315 Add a comment for translators for an error during resending
[MAILPOET-6241]
2024-12-30 16:50:55 +03:00
9876538c14 Update used Automate Woo plugin in Circle CI
- latest version: 6.1.4
 - previous version: 6.0.33
2024-12-30 12:20:11 +03:00
aad7030f3c Add abandoned cart worker to simple workers list
[MAILPOET-6404]
2024-12-30 09:45:22 +01:00
d7c10a48b6 Update postcss
[MAILPOET-6403]
2024-12-30 09:39:00 +01:00
709d5a8177 Release 5.5.2 2024-12-24 15:46:46 +03:00
e58405490b Update used WooCommerce Subscriptions plugin in Circle CI
- latest version: 7.0.0
 - previous version: 6.9.1
2024-12-23 19:20:49 +03:00
49164f6688 Update used WooCommerce plugin in Circle CI
- latest version: 9.5.1
 - previous version: 9.4.3
2024-12-23 19:20:49 +03:00
74dbbdd0af Avoid unnecessary transformation when adding tracking image
[MAILPOET-6400]
2024-12-23 16:18:45 +03:00
af05486fac Update mocks in Header and Footer renderers unit tests
[MAILPOET-6400]
2024-12-23 16:18:45 +03:00
384e8bf59f Fix deprecation warnings in unit tests
The missing property was causing multiple warnings in the test output.
Creation of dynamic property MailPoet\Test\Form\Block\RadioTest::$tester is deprecated
[MAILPOET-6400]
2024-12-23 16:18:45 +03:00
0d424ef037 Improve content rendering in Header and Footer blocks
[MAILPOET-6400]
2024-12-23 16:18:45 +03:00
77c54e2e2b Improve the stability of the EmailTemplatesCest
[MAILPOET-6356]
2024-12-20 15:14:30 +01:00
132ffde58f Fix saving template associations with emails
The original workaround was not working for templates that have edits saved in the DB.
The problem was that when the template is saved in the DB the get_block_templates()
returns WP_Block_Template object with post_types as null.
It seems this association is not saved to DB in the core.
[MAILPOET-6334]
2024-12-20 15:14:30 +01:00
91f90a03d1 Fix PHPStan errors after updating WordPress Stubs
[MAILPOET-6356]
2024-12-20 15:14:30 +01:00
82172969d1 Update szepeviktor/phpstan-wordpress for PHPStan
We need to udpate WordPress Stubs to recognize new register_block_template
function.
[MAILPOET-6356]
2024-12-20 15:14:30 +01:00
30f11dc9cc Use registered email post types for templates instead of hardcoded mailpoet_email
The general email template is registered and works with all post types that are
marked as email post types during editor initialization.
[MAILPOET-6356]
2024-12-20 15:14:30 +01:00
2c3932bdd3 Move simple-light template from the engine/package to the free plugin
The additional templates are registered by integrators.
This way, we will be able to use assets like images from MailPoet's CDN
and also various services from the plugins (e.g. CdnAssetsController)
[MAILPOET-6356]
2024-12-20 15:14:30 +01:00
6eca06780f Add action for registering email templates
This commit introduces a new action to trigger registering email templates.
We need a custom action for that because the email editor engine controls
when we register templates and when we don't. Currently, we still skip
registering templates when we detect the site editor page.
[MAILPOET-6356]
2024-12-20 15:14:30 +01:00
e5aeae7989 Add workaround for saving post-template association for non-block themes
[MAILPOET-6356]
2024-12-20 15:14:30 +01:00
9b9187bb3e Move the template_id construction logic to Templates class
[MAILPOET-6356]
2024-12-20 15:14:30 +01:00
a5db2564c8 Add post_types field to the template REST API response
We want to use post_type for filtering email templates.
There is a PR that adds this property https://github.com/WordPress/wordpress-develop/pull/7530
but it is not merged.
This commit added the property and also future compatibility check
so that we don't attempt to add it after the PR is merged.
[MAILPOET-6356]
2024-12-20 15:14:30 +01:00
ddd2108109 Fix a typo in a method name in Email_Editor
[MAILPOET-6356]
2024-12-20 15:14:30 +01:00
2e661f8b8e Remove code that is no longer necessary for the templates to work
[MAILPOET-6356]
2024-12-20 15:14:30 +01:00
2fc0ad3c9e Switch template registration to use register_block_template
[MAILPOET-6356]
2024-12-20 15:14:30 +01:00
62b77b724c Change callback and function names
[MAILPOET-6376]
2024-12-20 10:12:04 +01:00
e56fe9a95e Add support for replacing written Personalization Tags with attributes
[MAILPOET-6376]
2024-12-20 10:12:04 +01:00
0e13133499 Use valueToInsert in Personalization Tag modal
[MAILPOET-6376]
2024-12-20 10:12:04 +01:00
e4c80a09b6 Add new Personalization Tag property defining value to insert
[MAILPOET-6376]
2024-12-20 10:12:04 +01:00
6fbaebcc09 Add replacing Personalization Tags for subject and preheader
[MAILPOET-6376]
2024-12-20 10:12:04 +01:00
041d76830b Add filter replacing written Personalization Tags to email editor
[MAILPOET-6376]
2024-12-20 10:12:04 +01:00
9b0cce9c0d Skip permission-callback scan for the line
The endpoint container can only return a Endpoint instance and checkPermissions
returns always a boolean. The QIT check therefore is a false positive

[MAILPOET-6398]
2024-12-19 15:00:47 +02:00
891bc34efa Fix switching to template mode
When we switch to template mode RichTextButton, which is dependent
on mailpoetData fails to render. The panel is hidden but it is hidden
in a subsequent render so we need to add check if mailpoet data are available.
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
635ba35a52 Add small comment and performance improvements
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
0b44ccdb4a Use @ts-expect-error instead of @ts-ignore
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
9edd4a6096 Add link into modal header
I unified the link with the link in details panel.
The target link should be replaced later in a different task.
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
cece3711f8 Use useCallback for insert functions
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
bc1581b174 Change rich-text-utils filename extension
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
2aae43b91e Create new richText component with button
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
b264c74ce9 Refactor modal to pass insert callback and isOpened value
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
64264460e8 Refactor initial fetch tags into resolver
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
cc38100109 Move common functions into utils file
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
0173ddd38e Add inserting personalization tags to text blocks
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
29c1f7462a Add inserting personalization tags to subject and preheader
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
bbe2f988e0 Add onInsert callback into PersonalizationTags from store
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
a570fa1641 Wrap personalization Tag token with square brackets
Because Gutenberg RichText component does not render square brackets around the HTML comment.
We need to append those brackets to tag tokens and expected them when we replace tags by their values.
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
74c2a99e80 Refactor category modal into smaller components
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
74e4b333ac Add search for filtering Personalization Tags by query
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
9282cf91c6 Add filtering personalization tags by category
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
d17faaa13a Add rendering Personalization tags to modal
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
2c7c815e0a Add Site Personalization Tags
A new category of personalization tags can help me with design implementation.
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
2c031b01fc Add loading personalization to store
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
bcc07c7503 Add API endpoint returning registered personalization tags
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
3a3b53545f Add personalization tags modal component
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
1d11502e93 Add personalizationTags state to custom editor
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
7f2f9ff7ca Add button with shortcode icon for subject and preheader
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
99d4c3bcaf Add button with shortcode icon into richText panel
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
1a9b711b1f Replace TextArea by RichText component in Email editor details panel
RichText component allows us using HTML comments for subject and preheader
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
20409a39dd Add rule for ts and js files to the .editorconfig
The new rule uses tabs which is with alignment with WP Coding style.
[MAILPOET-6354]
2024-12-18 14:15:05 +01:00
22f9707505 Remove redundant rich-text config from webpack
[MAILPOET-6387]
2024-12-18 09:54:39 +01:00
cd9b8dab64 Add missing CSS for HTML comments in RichText
Because CSS for HTML comments in RichText is a part of BlockEditor,
and we want to minimize the plugin build, this commit adds the necessary CSS.
[MAILPOET-6387]
2024-12-18 09:54:39 +01:00
2f0cec5fde Replace WP Rich Text package by our build with version 7.14.0
[MAILPOET-6387]
2024-12-18 09:54:39 +01:00
ea894e2917 Add config for RichText package into webpack config
[MAILPOET-6387]
2024-12-18 09:54:39 +01:00
132c247d97 Update email-editor @wordpress/rich-text dependency to 7.14.0
[MAILPOET-6387]
2024-12-18 09:54:39 +01:00
3ce8e38a00 Remove unused method from Email_editor class
[MAILPOET-6387]
2024-12-18 09:54:39 +01:00
363382d2a4 Make PHP notice version-agnostic for translators
[MAILPOET-6389]
2024-12-18 10:01:19 +02:00
7e282fa03a Fix Uncaught ArgumentCountError: 4 arguments are required, 3 given
[MAILPOET-6389]
2024-12-18 10:01:19 +02:00
38cd7491be Remove hinting to using an outdated version
[MAILPOET-6389]
2024-12-18 10:01:19 +02:00
a7feee3c48 Remove old deactivation method
[MAILPOET-6389]
2024-12-18 10:01:19 +02:00
d6b4fd9bc6 Execute plugin only when requirements are met.
Instead of deactivating, we just do not require the autoloader and do not initialize
the plugin. We only show the notices in the admin.

[MAILPOET-6389]
2024-12-18 10:01:19 +02:00
c37800bca8 Group admin notices together
[MAILPOET-6389]
2024-12-18 10:01:19 +02:00
0d6acde41a Release 5.5.1 2024-12-18 08:28:11 +02:00
513ba77b22 Ensure wcsGetBillingPeriodStrings always returns an array
We noticed some errors in logs when the function returned another value.
This can be caused by a filter inside wcs_get_subscription_period_strings
The rest of our code expects an array, so if the function doesn't return an array,
let's return an empty array to avoid crashes.
[PREMIUM-288]
2024-12-17 14:31:23 +01:00
c0e61fbdc4 Refactor overlooked test class names
We favor "Captcha" prefix over "BuiltInCaptcha." A refactoring has been already pushed for that. This has been overlooked.

[MAILPOET-6325]
2024-12-17 13:56:00 +02:00
7b86b932c3 Fix duplicate MailPoet page in settings
Fixes an issue where two MP pages with the same name appears in page selection under Setting -> Basics for some settings like "Manage subscription page."

[MAILPOET-6325]
2024-12-17 13:56:00 +02:00
6f9c71faf1 Add a new page for built-in CAPTCHA rendering
The page to render the built-in CAPTCHA carry the 'subscriptions' name, which is not fitting for usage outside MP's subscriptions context.

Previously, CAPTCHA in render in this page:
/?mailpoet_page=subscriptions&(...)

This has been changed to:
/?mailpoet_page=captcha&(...)

[MAILPOET-6325]
2024-12-17 13:56:00 +02:00
84999fde99 Refactor hard-coded page name to constant
[MAILPOET-6325]
2024-12-17 13:56:00 +02:00
9ff838f964 Revert "Adjust MP's page name to template"
[MAILPOET-6325]
2024-12-17 13:56:00 +02:00
99717e5de8 Rename a variable for readability
[MAILPOET-6325]
2024-12-17 13:56:00 +02:00
7f606234a3 Fix unnecessary call to exit in CAPTCHA refresh
Upon refactoring, this was added by mistake

[MAILPOET-6325]
2024-12-17 13:56:00 +02:00
2d4e8f4df6 Fix broken integration & acceptance tests 2024-12-17 13:56:00 +02:00
93eb0813f9 Fix broken import statements upon rebasing 2024-12-17 13:56:00 +02:00
bd218fb503 Add built-in CAPTCHA in WC register form
[MAILPOET-6325]
2024-12-17 13:56:00 +02:00
0ba53c660f Validate built-in CAPTCHA in WP register form
[MAILPOET-6325]
2024-12-17 13:56:00 +02:00
9c38938a72 Render built-in CAPTCHA in WP register form
[MAILPOET-6325]
2024-12-17 13:56:00 +02:00
df171fdcc7 Add JSON endpoint for CAPTCHA rendering
To be used inside WP/WC registration form to construct URL for CAPTCHA page.

[MAILPOET-6325]
2024-12-17 13:56:00 +02:00
d2ebfba8c3 Fix PHPStorm don't force comma on last array element
This conflict with the project's coding standard, specifically with this rule:

SlevomatCodingStandard.Arrays.TrailingArrayComma.MissingTrailingComma
2024-12-17 13:56:00 +02:00
995190108c Abstract MP form details in CAPTCHA form renderer
A preliminary step to enable built-in CAPTCHA in external forms, specifically for WP/WC registration form.
2024-12-17 13:56:00 +02:00
798cb26445 Minor polishing for CAPTCHA form renderer 2024-12-17 13:56:00 +02:00
8744ddde1c Clean up dead endpoints in subscription router 2024-12-17 13:56:00 +02:00
60d579da6a Remove no longer used code for CAPTCHA refresh 2024-12-17 13:56:00 +02:00
0230099c92 Migrate refresh URL in built-in CAPTCHA form 2024-12-17 13:56:00 +02:00
f8787f45c0 Add 'refresh' phrase action to CAPTCHA router 2024-12-17 13:56:00 +02:00
53a7df4eea Remove no longer used code for CAPTCHA audio 2024-12-17 13:56:00 +02:00
1e0ee91f1c Migrate audio URL in built-in CAPTCHA form 2024-12-17 13:56:00 +02:00
78de943ed0 Add 'audio' rendering action to CAPTCHA router 2024-12-17 13:56:00 +02:00
28b92ed349 Remove no longer used code for CAPTCHA image 2024-12-17 13:56:00 +02:00
57e56b15bc Migrate image URL in built-in CAPTCHA form 2024-12-17 13:56:00 +02:00
edbe8df310 Add 'image' rendering action to CAPTCHA router 2024-12-17 13:56:00 +02:00
5992708be3 Remove no longer used code for CAPTCHA rendering 2024-12-17 13:56:00 +02:00
720ec613df Use newly created CAPTCHA router for rendering 2024-12-17 13:56:00 +02:00
3bda992f13 Move CAPTCHA classes under MailPoet\Captcha dir
CAPTCHA usage is no longer tied to MP's subscription form.
2024-12-17 13:56:00 +02:00
8e608816a9 Rename a class for consistency
Aligns the name with other builtin CAPTCHA classes, which all starts with 'Captcha.'
2024-12-17 13:56:00 +02:00
c8577b0611 Remove pointless abstraction in built-in CAPTCHA
Pointless. Not referenced except in implementation classes.
2024-12-17 13:56:00 +02:00
8e9c9c5bda Adjust MP's page name to 'template'
The page for the builtin CAPTCHA carry the 'subscriptions' name, which is not fitting to use outside MP's subscriptions context.

This adjusts the mailpoet page from:
/?mailpoet_page=subscriptions

To this link:
/?mailpoet_page=template
2024-12-17 13:56:00 +02:00
57b1635c24 Render built-in CAPTCHA form in dedicated page
Adds a new router for MP's pages:

/?mailpoet_page=subscriptions&mailpoet_router&endpoint=captcha&action=render

A preliminary step to provide builtin CAPTCHA for WP/WC registration form. Currently, builtin CAPTCHA is rendered under subscription-specific params:

/?mailpoet_page=subscriptions&mailpoet_router&endpoint=subscription&action=captcha
2024-12-17 13:56:00 +02:00
e1e079e1a5 Update selenium + chrome image in sample config for Mx Macs
[MAILPOET-6335]
2024-12-17 10:36:39 +01:00
43f7542c64 Improve the look of labels in the save items popup in the editor
[MAILPOET-6335]
2024-12-17 10:36:39 +01:00
c64e4caf27 Remove styles data added to templates REST API response
We no longer need to send CSS for every template because we use global styles
live from the editor.
[MAILPOET-6335]
2024-12-17 10:36:39 +01:00
bc10ae7216 Cleanup JS code from styles - template association
[MAILPOET-6335]
2024-12-17 10:36:39 +01:00
269b55ed08 Use current styles from the store for template previews in the selector
This commit ensures that templates are previewed with the latest styles
set in the editor. Previously, we were using the version sent from the server that
might be out of date.
[MAILPOET-6335]
2024-12-17 10:36:39 +01:00
6472021359 Update notice text when saving template or global styles
The code triggers the same notice for changes in a template or changes in global styles.
This commit makes the text of the notice more generic to work for both.
[MAILPOET-6335]
2024-12-17 10:36:39 +01:00
7f61415a39 Speed up email editor start by preloading REST API requests
[MAILPOET-6335]
2024-12-17 10:36:39 +01:00
d1166edbd8 Cleanup user styles before applying
We need to remove empty values that may occur when the user resets a value.
These empty values prevent applying defaults coming from editor theme after reset.
[MAILPOET-6335]
2024-12-17 10:36:39 +01:00
c908cabcf6 Fix saving styles to save only user-edited props
There was a typo in StylesColorPanel property, and we were passing incorrect values.
StylesColorPanel.value expects user set values
StylesColorPanel.inheritedValue expects merged styles
See b66f9ff095/packages/edit-site/src/components/global-styles/screen-colors.js (L23-L28)
[MAILPOET-6335]
2024-12-17 10:36:39 +01:00
b5e8cf84c8 Fix issue with CSS variables in the style panel
Some components in the style setting (e.g., SpacingSizesControl) don't work
with the CSS variables when present in valid CSS form (e.g., var(--wp--preset--spacing--10)).
To prevent issues, we need to transform CSS variables to the shortened variant.
The core uses more sophisticated functions for that, see
f2ba0fdb4c/packages/block-editor/src/components/global-styles/utils.js (L307-L358)
The functionality is private, so I've created a simpler version.
[MAILPOET-6335]
2024-12-17 10:36:39 +01:00
ebe7151269 Remove code related to template themes
[MAILPOET-6335]
2024-12-17 10:36:39 +01:00
1e1bec4ce0 Use user theme in renderer instead of template themes
We no longer read styles associate with templates when we render an email
but we read the user theme instead
[MAILPOET-6335]
2024-12-17 10:36:39 +01:00
15818f37ef Add user theme post cleanup to integration tests
This commit adds automatic cleanup of the user theme post before every test
[MAILPOET-6335]
2024-12-17 10:36:39 +01:00
993cbb4fd7 Run cleanup after each integration test
This is needed to get rid of posts created in tests to prevent test interdependency
[MAILPOET-6335]
2024-12-17 10:36:39 +01:00
fdc0d15b63 Load user styles in the email editor properly
[MAILPOET-6335]
2024-12-17 10:36:39 +01:00
0f7009438c Add User_Theme class for managing user-defined styles and settings
[MAILPOET-6335]
2024-12-17 10:36:39 +01:00
de03e84eb4 Use global styles aka user theme for editor styles
[MAILPOET-6335]
2024-12-17 10:36:39 +01:00
8f512a7967 Add hook for working with email global styles
[MAILPOET-6335]
2024-12-17 10:36:39 +01:00
f906cd686f Add functionality for fetching global styles from server
[MAILPOET-6335]
2024-12-17 10:36:39 +01:00
708969954a Update dependencies
MAILPOET-6383
2024-12-13 15:54:53 +01:00
3ea73b807f Remove window properties used in Beamer
[MAILPOET-6375]
2024-12-13 09:11:12 +01:00
b8419c513c Remove Beamer component
[MAILPOET-6375]
2024-12-13 09:11:12 +01:00
040d09a25c Retain Tutorial icon in email editor
[MAILPOET-6375]
2024-12-13 09:11:12 +01:00
296111a89a Remove Beamer from readme.txt list of 3rd party services
[MAILPOET-6375]
2024-12-13 09:11:12 +01:00
b93bb81a98 Remove Beamer integration from TopBar component
[MAILPOET-6375]
2024-12-13 09:11:12 +01:00
2d4d29196f Remove Beamer cron worker
[MAILPOET-6375]
2024-12-13 09:11:12 +01:00
1c8771efef Fix other weird PHP fatal errors
MAILPOET-6382
2024-12-12 21:30:03 +01:00
8a4ea2d899 Fix PHP fatal error caused by using mailpoet_settings DB table before it's available
MAILPOET-6382
2024-12-12 21:30:03 +01:00
1ca3044639 Release 5.5.0 2024-12-10 14:24:32 +01:00
cd540f7b5d Refactor email editor acceptance test skipping code
[MAILPOET-6374]
2024-12-10 10:55:02 +01:00
8fe52e6979 Allow skipping email editor templates test
We need to skip this test because email editor doesn't support
older WP versions.
[MAILPOET-6374]
2024-12-10 10:55:02 +01:00
08ba9b1da9 Fix acceptance test
MAILPOET-5949
2024-12-09 17:06:48 +01:00
36130c9809 Ensure "Start from scratch" button sticks to the end of the modal
MAILPOET-5949
2024-12-09 17:06:48 +01:00
52a6122e74 Fix header and footer not showing for recent category email post templates
MAILPOET-5949
2024-12-09 17:06:48 +01:00
4f948dfd65 Filter out empty email post-content
MAILPOET-5949
2024-12-09 17:06:48 +01:00
f79c0cec55 Update template selector styles
MAILPOET-5949
2024-12-09 17:06:48 +01:00
a80a6bf5c5 Refactor SelectTemplateBody and use memo and useEffect when required to improve render performance
MAILPOET-5949
2024-12-09 17:06:48 +01:00
8661a169b3 Add basic optimization for usePreviewTemplates to improve render performance
MAILPOET-5949
2024-12-09 17:06:48 +01:00
bc0ce09d61 Add support for email-general and email-simple templates
The previous implementation only checks for email-general templates

MAILPOET-5949
2024-12-09 17:06:48 +01:00
fb5166ab7c Fix an edge case where it might be possible for email content to have similar post-slug
MAILPOET-5949
2024-12-09 17:06:48 +01:00
16e4346d07 Fix using sent email post content as new email editor page template
MAILPOET-5949
2024-12-09 17:06:48 +01:00
651e80b8f0 Fetch emailPosts for use in template selection modal
MAILPOET-5949
2024-12-09 17:06:48 +01:00
17bda157aa Add Selector to fetch mailpoet email editor post-types
MAILPOET-5949
2024-12-09 17:06:48 +01:00
9e9974d694 Polish is an official translation now
[MAILPOET-6372]
2024-12-09 16:26:23 +02:00
80963a0667 Ensure we pass a string to CaptchaFormRenderer::getCaptchaPageContent()
[MAILPOET-6348]
2024-12-09 15:08:00 +01:00
d6d71c7cc3 Ensure the API request data are string
In case an array was passed to an endpoint or token, there was a fatal error.
[MAILPOET-6348]
2024-12-09 15:08:00 +01:00
ea6c705a97 Ensure that router endpoint and action are string
In case they were an array there was a Fatal Error because we use strict type
and method_exists and ucfirst require string.
[MAILPOET-6348]
2024-12-09 15:08:00 +01:00
c35bf6a008 Fix double sidebar header
The issue was fixed in @wordpress/interface but we were using
the older version.
The @wordpress/interface is not distributed standalone in WP Core
so we bundle it.
[MAILPOET-6371]
2024-12-09 14:47:09 +01:00
23b5af7fc4 Update templates acceptance tests
[MAILPOET-6342]
2024-12-09 14:16:04 +01:00
e181725127 Change the texts in the component with changes to save to match email context
This should be removed after the upstream
contextualize the template texts to match associated post types or uses more generic texts.
See https://github.com/WordPress/gutenberg/issues/67697
[MAILPOET-6342]
2024-12-09 14:16:04 +01:00
4b761ac74d Cleanup SaveEmailButton to work only with email
[MAILPOET-6342]
2024-12-09 14:16:04 +01:00
2e52419ffd Add save all button and logic for displaying it in the header
[MAILPOET-6342]
2024-12-09 14:16:04 +01:00
5b443027bf Rename SaveButton to SaveEmailButton
This component will be used for saving changes only in email content.
It is a link variant button and will still be present next to Save/Send button.
[MAILPOET-6342]
2024-12-09 14:16:04 +01:00
d5c8566dd0 Unpause only newer sending tasks and mark older ones as failed
[MAILPOET-6241]
2024-12-09 13:31:49 +01:00
80c1888edd Set proper status by typing in newsletter update and resume sending
[MAILPOET-6241]
2024-12-09 13:31:49 +01:00
babc7453ad Fix the resend button success callback in Sending status page
The listing update after the resend action was not working.
This commit fixes it.
[MAILPOET-6241]
2024-12-09 13:31:49 +01:00
e7ae20f689 Add refreshRef to listing
This commit adds a simple mechanism to trigger the refresh of the listing
from a parent component.
This is to replace window.mailpoet_listing.forceUpdate which is no longer available
but still used in sending-status.jsx causing errors in the console.

[MAILPOET-6241]
2024-12-09 13:31:49 +01:00
a9e64503b7 Add re-engagement email into activable emails
[MAILPOET-6241]
2024-12-09 13:31:49 +01:00
301a9a71f1 Add migration for fixing the incorrect status of automation emails
[MAILPOET-6241]
2024-12-09 13:31:49 +01:00
55f2d83abb Prevent resending emails in case the email is not active
Automation email needs to be active in order to be sent.
If we allow resending to inactive emails, we would need to activate them first,
but this could be an unexpected side effect. And activating may cause sending other paused tasks as a side effect.
I expect the email to be active in the majority of cases, so users should not meet this notice very often.
[MAILPOET-6241]
2024-12-09 13:31:49 +01:00
79de8cc17c Set proper status when resending activable newsletter type
[MAILPOET-6241]
2024-12-09 13:31:49 +01:00
ab3d6a1fcb Add NewsletterEntity::canBeSetActive
[MAILPOET-6241]
2024-12-09 13:31:49 +01:00
2ed8dfd76b Add automation emails to activable email check
[MAILPOET-6241]
2024-12-09 13:31:49 +01:00
3acdd311a7 Fix issues preventing CodeQL from scanning the repo.
5d0eaf595f
2024-12-09 11:57:22 +01:00
282c987c39 Fix failing acceptance test
MAILPOET-6331
2024-12-09 10:30:42 +01:00
fbf4272e0e Update email editor acceptance test
MAILPOET-6331
2024-12-09 10:30:42 +01:00
8b1f7c9a88 Fix lint style errors
MAILPOET-6331
2024-12-09 10:30:42 +01:00
2896ed45eb Add text information for recent category templates
MAILPOET-6331
2024-12-09 10:30:42 +01:00
cec952fbde Add help icon to recent button
MAILPOET-6331
2024-12-09 10:30:42 +01:00
cb091e0dc6 Add support for basic tab navigation when selecting template
MAILPOET-6331
2024-12-09 10:30:42 +01:00
5743ccbc5f Separate SelectTemplateModal into smaller components
MAILPOET-6331
2024-12-09 10:30:42 +01:00
d6415e07e1 Sanitise post id before constructing URL
Fixes: https://github.com/mailpoet/mailpoet/security/code-scanning/17
2024-12-09 10:09:10 +01:00
ca75489ab0 Update used Automate Woo plugin in Circle CI
- latest version: 6.1.3
 - previous version: 6.0.33
2024-12-09 10:06:19 +01:00
e028d96ebb Update used WooCommerce plugin in Circle CI
- latest version: 9.4.3
 - previous version: 9.3.4
2024-12-09 10:06:19 +01:00
f01596322b Update text in templates acceptance test
[MAILPOET-6336]
2024-12-06 13:07:52 +01:00
411943f39b Add a workaround for replacing core notice Site updated
I considered doing this using a filter 'i18n.gettext', but
with this approach, we would just replace the text. The notice also
contained an action with a link to the site's homepage, so I chose this mechanism instead.
Let's see if there will be more use-cases. We can eventually move it somewhere into the store
and proxy all messages via our store.
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
2334805b95 Use more informative text in the reset template dialog
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
1ce1ddc952 Add the cancel button to modal when switching to template mode
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
8b3f7a489f Add missing translation function to template info panel
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
8505f5b174 Add basic acceptance test for template edit, swap and restore
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
45e0e56389 Hide command palette shortcut
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
d682b82bc5 Update variant of the dropdown button to match the native editor
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
4b29658adc Remove experimental templates panel
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
10b2c2b648 Use current email content when previewing templates when swapping
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
1fdda485d3 Add basic swap template functionality
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
9f273a3ff2 Add edit template modal
[MAILPOET-6336
2024-12-06 12:21:19 +01:00
7811535e72 Add dropdown with edit and swap template buttons
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
1717a0a235 Extract template reset modal to an extra component
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
c7049468c2 Add revert template confirmation modal
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
fb74526d9d Move revert template function from component file to store action
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
ebefee4de7 Add template actions menu toggle with dummy reset template action
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
9ebcf9b506 Add info text to the template info panel in sidebar.
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
1cff0c5ee1 Update text in template mode warning popup
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
c612eb1c4e Rename document tab in sidebar based on editor mode
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
ed8d64816c Rename mainSidebarEmailTab constant to mainSidebarDocumentTab
The email name was misleading because in the template mode we want to show Template.
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
ab00d505b9 Replace logic for detection of editor mode by the useEditorMode hook
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
02dabf9c01 Add a custom hook to determine whether we are in email or template mode
There are a couple of places where we determine the mode, but we use different approaches.
This commit adds a mechanism for determining the editor mode which can be easily reusable
in the whole app.
[MAILPOET-6336]
2024-12-06 12:21:19 +01:00
21dde5362a Fix copy as reported by Translation team 2024-12-06 11:19:42 +01:00
b3801f3f54 Allow usage of classes in links
[MAILPOET-6360]
2024-12-05 14:07:46 +01:00
677c8af6fa Update the modal dialogue copy
[MAILPOET-6330]
2024-12-05 08:51:01 +01:00
662258e9df Update the modal dialogue copy
[MAILPOET-6330]
2024-12-05 08:51:01 +01:00
59666c3110 Update the button for using the new editor
[MAILPOET-6330]
2024-12-05 08:51:01 +01:00
cd184c373c Update readme, implement PR feedback
MAILPOET-6256
2024-12-04 14:48:04 +01:00
8c2ede4ff9 Update Readme documentation
MAILPOET-6256
2024-12-04 14:48:04 +01:00
98bc96b1b8 Add loading state and remove custom button position.
Based on PR feedback https://github.com/mailpoet/mailpoet/pull/5972#issuecomment-2516596159, The Email editor cannot work without a template. So, we currently don't need to set up workflow to support template not loading

MAILPOET-6331
2024-12-04 13:29:00 +01:00
abf03d6cc7 Update "Start from scratch" button styles when no template is registered
MAILPOET-6333
2024-12-04 13:29:00 +01:00
46c8ae94bc Add "Start from scratch" to the template selector
MAILPOET-6333
2024-12-04 13:29:00 +01:00
f952ee0d1f Remove 'Check your sending method settings.' text for MailPoet method
[MAILPOET-6357]
2024-12-03 16:01:37 +02:00
7bf5642107 Improve Banned Message
[MAILPOET-6357]
2024-12-03 16:01:37 +02:00
cb9c2fd88f Release 5.4.2 2024-12-03 14:31:30 +01:00
a5f0dbc2a3 Fix PHPStan and update git-blame-ignore 2024-12-03 09:32:42 +01:00
64b550e27d Update Theme_Controller_Test, add case for loading theme.json file
MAILPOET-6043
2024-12-02 14:21:54 +01:00
5d6d7eba57 Add template integration tests
MAILPOET-6043
2024-12-02 14:21:54 +01:00
0a87464b42 Disable block patterns caching
caching is dependent on the path, however it differs for the test run and wp-cli so it produces notices and tests fail
[MAILPOET-6353]
2024-12-02 12:01:54 +01:00
e6abec74d4 Refactor SubscriberFinder::addSubscribersToTaskFromSegments to return void
We removed the return value to prevent us from using it to check if there were recipients.
It is not 100% reliable for that purpose because it returns 0 for a repeated call.
[MAILPOET-6346]
2024-12-02 11:45:10 +01:00
74de985620 Fix scheduling automation emails with prefilled subscribers queue
[MAILPOET-6346]
2024-12-02 11:45:10 +01:00
59154a20f4 Fix scheduling post notifications with prefilled subscribers queue
[MAILPOET-6346]
2024-12-02 11:45:10 +01:00
189663e22a Remove sale from .org description
[MAILPOET-6283]
2024-12-02 10:29:38 +01:00
b242fea6ec Update 700,000 to 600,000 users
[MAILPOET-6344]
2024-12-02 10:22:34 +01:00
56dca6412a Replace incorrect use of _x() with __()
[MAILPOET-6344]
2024-12-02 10:22:34 +01:00
31b2779c8f Update cross-spawn
[MAILPOET-6355]
2024-12-02 10:06:39 +01:00
b49970e26e Simplify GitHub workflow config for PHPStan
MAILPOET-6318
2024-12-02 08:44:22 +01:00
0b982ddb5c Remove unnessary PHPStan ignore errors
MAILPOET-6318
2024-12-02 08:44:22 +01:00
6df51455d2 Fix PHPStan errors
MAILPOET-6318
2024-12-02 08:44:22 +01:00
9a6225873c Fix email editor GitHub workflow
MAILPOET-6318
2024-12-02 08:44:22 +01:00
ccc3f9ab28 Ensure phpstan exit code is passed along to the shell window and address some pr comments
MAILPOET-6318
2024-12-02 08:44:22 +01:00
b1cc53ec5b Update comments and fix code style warnings
MAILPOET-6318
2024-12-02 08:44:22 +01:00
a15f8ba562 Load custom config for PHPStan based on the provided PHP version
MAILPOET-6318
2024-12-02 08:44:22 +01:00
5ce9008f90 Fix PHPStan class-string errors
MAILPOET-6318
2024-12-02 08:44:22 +01:00
cbfdba7bd2 Fix PHPStan PHP 8.2 error
MAILPOET-6318
2024-12-02 08:44:22 +01:00
0ac7a1ee02 Fix Bootstrap file IntegrationTesterActions.php does not exist.
MAILPOET-6318
2024-12-02 08:44:22 +01:00
6066fd6321 Automatically fix fixable code style lint errors
MAILPOET-6318
2024-12-02 08:44:22 +01:00
325c4c74f4 Fix PHPStan errors for Email editor PHP package integration test folder
MAILPOET-6318
2024-12-02 08:44:22 +01:00
a4ad960492 Fix PHPStan errors for Email editor PHP package unit test folder
MAILPOET-6318
2024-12-02 08:44:22 +01:00
bb71448c53 Fix PHPStan errors for Email editor PHP package src folder
MAILPOET-6318
2024-12-02 08:44:22 +01:00
40aac9e65c Use email editor custom config for phpstan
MAILPOET-6318
2024-12-02 08:44:22 +01:00
9102ec9735 Fix github action error Bootstrap file mailpoet/vendor does not exist
MAILPOET-6318
2024-12-02 08:44:22 +01:00
b18329a11b Add github action for phpstan
MAILPOET-6318
2024-12-02 08:44:22 +01:00
30c4b5687f Add phpstan command and script to Email editor PHP package
MAILPOET-6318
2024-12-02 08:44:22 +01:00
098c02f71d Update used WooCommerce Subscriptions plugin in Circle CI
- latest version: 6.9.1
 - previous version: 6.8.0
2024-12-02 07:20:17 +01:00
ea3f11119e Fix plugin deactivation in test
We need to deactivate the premium plugin first. The premium is now marked as dependent on the free
and free can't be deactivated.
This became necessary after https://github.com/mailpoet/mailpoet-premium/pull/924
was merged.
2024-11-29 21:18:48 +01:00
0b6a53ab7d Skip Gutenberg Editor acceptance test for WP below 6.7
We use \HTML_Tag_Processor::set_modifiable_text, which is not available in 6.6
[MAILPOET-6353]
2024-11-29 21:18:48 +01:00
9b0880c0ef Refactor HTML_Tag_Processor_Test integration test
[MAILPOET-6328]
2024-11-28 15:01:04 +01:00
1c20730817 Improve comments across Personalization Tags classes
[MAILPOET-6328]
2024-11-28 15:01:04 +01:00
f95688ca70 Add new class Personalization_Tag
The new class contains all necessary data to replace token with personalized value.
[MAILPOET-6328]
2024-11-28 15:01:04 +01:00
829905a0f5 Move Personalizer to a different namespace
[MAILPOET-6328]
2024-11-28 15:01:04 +01:00
eee1f3a652 Personalize email created via Gutenberg email editor
[MAILPOET-6328]
2024-11-28 15:01:04 +01:00
7d3ba0ae20 Register subscriber Personalization Tags in gutenberg editor
This commit adds a new class which register MailPoet subscribers tags for the new email editor.
[MAILPOET-6328]
2024-11-28 15:01:04 +01:00
7aad021735 Add Personalization Tags support for title
[MAILPOET-6328]
2024-11-28 15:01:04 +01:00
a761799c61 Add new class Personalizer managing tags replacement
[MAILPOET-6328]
2024-11-28 15:01:04 +01:00
806e960190 Add new class extending WP_HTML_Tag_Processor
The new class allows replacing tokens which is necessary for Personalization Tags implementation.
[MAILPOET-6328]
2024-11-28 15:01:04 +01:00
aab08fa5ab Add personalization-tag-registry class
The new class which allows register Personalization Tags and then read them.
[MAILPOET-6328]
2024-11-28 15:01:04 +01:00
8a32099af7 Update test for resending confirmation emails
[MAILPOET-6329]
2024-11-28 11:15:47 +01:00
88c1e53899 Small simplifications to the code
[MAILPOET-6329]
2024-11-28 11:15:47 +01:00
d76c33afd0 Show "Resend confirmation email" link regardless of number of sent confirmations
[MAILPOET-6329]
2024-11-28 11:15:47 +01:00
3386f9f4f1 Fix eslint warnings: Post not found and useSelect has a missing dependency
MAILPOET-6316
2024-11-27 18:02:35 +01:00
f9458c2b7f Fix eslint warnings: block and blockinstance
MAILPOET-6316
2024-11-27 18:02:35 +01:00
9686da2918 Add timeout to the first k6 test manually 2024-11-27 12:03:54 +01:00
09356b699b Use the newest PHP8.2 in Circle CI jobs
[MAILPOET-6347]
2024-11-27 11:40:26 +01:00
1966739a48 Use images with the latest php8.2 version in tests
[MAILPOET-6347]
2024-11-27 11:40:26 +01:00
fd0294309c Updated required and tested up to WordPress and WooCommerce versions
[MAILPOET-6345]
2024-11-27 09:51:23 +01:00
324e02f2cf Remove redundant lock_unlock.js
[MAILPOET-6319]
2024-11-26 16:44:11 +01:00
b1c8f2cc0e Remove double import of block editor private apis
[MAILPOET-6319]
2024-11-26 16:44:11 +01:00
8d1d32a213 Add very simple readme for private APIs
[MAILPOET-6319]
2024-11-26 16:44:11 +01:00
7ad7e45d07 Remove root unlock from email editor
[MAILPOET-6319]
2024-11-26 16:44:11 +01:00
0431e5eb25 Consume useGlobalStylesOutputWithConfig from private-apis
[MAILPOET-6319]
2024-11-26 16:44:11 +01:00
b631e509ef Export StylesColorPanel from private-apis file
[MAILPOET-6319]
2024-11-26 16:44:11 +01:00
ceecfe69a5 Move unlocking core store and block editor store to private apis
[MAILPOET-6319]
2024-11-26 16:44:11 +01:00
d8a3289414 Remove unnecessary unlock of editor settings
The selector is public.
[MAILPOET-6319]
2024-11-26 16:44:11 +01:00
cac56f3563 Move Tabs to private and document usage
[MAILPOET-6319]
2024-11-26 16:44:11 +01:00
fbdfc61eaa Move BlockCanvas to private APIs
[MAILPOET-6319]
2024-11-26 16:44:11 +01:00
c72b0b6f79 Get rid of useFlashEditableBlocks
It is a private API which is not critical for our application.
It shortly highlights blocks that are editable after a click in the parent.
As it is not critical and is private, it is a risk, and we should rather not use it.
[MAILPOET-6319]
2024-11-26 16:44:11 +01:00
5bbdc41679 Add forward compatibility for template-locked mode
The setting was added in https://github.com/WordPress/gutenberg/pull/62304
and is needed with the newest Gutenberg version.
[MAILPOET-6319]
2024-11-26 16:44:11 +01:00
13bf305aeb Update filter name and add reason for ts-ignore
MAILPOET-6315
2024-11-26 13:50:53 +01:00
02d424d8a1 Fix NpsPoll CSS style issues
MAILPOET-6315
2024-11-26 13:50:53 +01:00
14ee0340a1 Fix NpsPoll component loading error
MAILPOET-6315
2024-11-26 13:50:53 +01:00
d8a1459bf5 Add missing variables to EditorPageRenderer.php
MAILPOET-6315
2024-11-26 13:50:53 +01:00
9dbe6492d8 Refactor ReviewRequest component to tsx and move translation function to @wordpress/i18n
MAILPOET-6315
2024-11-26 13:50:53 +01:00
b9b503889d Add NpsPoll feature support for Email editor
MAILPOET-6315
2024-11-26 13:50:53 +01:00
116e20f89b Ensure initializeMixpanelWhenLoaded is only executed a limited about of time
The current implementation keeps calling `initializeMixpanelWhenLoaded` an unlimited amount of time when `mixpanel` does not exist. This has a negative performance impact on the application.
For example, The mixpanel object does not exist in the email editor context.

MAILPOET-6315
2024-11-26 13:50:53 +01:00
be94c8e2b9 Release 5.4.1 2024-11-26 13:12:02 +01:00
564277f539 Update k6 browser timeout in RoboFile 2024-11-26 11:13:35 +01:00
b7f93bb358 Move settings test to the top 2024-11-25 19:01:52 +01:00
f6e11d6432 Improve the statsPage test more and move banner check upper 2024-11-25 17:17:43 +03:00
ab0412049d Improve stats page test to include checks for stats 2024-11-25 17:17:43 +03:00
59119ceb02 Show BFCM sale info in WP.org description
[MAILPOET-6283]
2024-11-25 11:28:41 +01:00
854867404a Update used Automate Woo plugin in Circle CI
- latest version: 6.1.2
 - previous version: 6.0.33
2024-11-25 08:52:07 +01:00
d7b259d264 Update used WooCommerce plugin in Circle CI
- latest version: 9.4.2
 - previous version: 9.3.3
2024-11-25 08:52:07 +01:00
eebd93d0f0 Update used WordPress images in Circle CI
- latest version: 6.7.1-php8.3
 - previous version: 6.6.2
2024-11-25 08:52:07 +01:00
ea181cfbd0 Fix free plugin unit tests to run locally in docker
[MAILPOET-6244]
2024-11-22 17:40:25 +01:00
9493ef70e4 Fix unit tests in the free plugin
[MAILPOET-6244]
2024-11-22 17:40:25 +01:00
9e2c95ae73 Use Woo native function when creating a customer in tests
Not using the native function was causing hidden errors
"User XX not found when creating customer." which were logged but
didn't break tests.
Using the Woo's function wc_create_new_customer prevents these errors.
[MAILPOET-6244]
2024-11-22 17:40:25 +01:00
a8224d511f Update codecept path in RoboFile
[MAILPOET-6244]
2024-11-22 17:40:25 +01:00
8e9a38589a Update integration tests to work with updated Codeception/stub
[MAILPOET-6244]
2024-11-22 17:40:25 +01:00
d42b92c930 Fix acceptance tests in free plugin
[MAILPOET-6244]
2024-11-22 17:40:25 +01:00
beb2994a71 Fix php8.2 deprecation warnings in email editor integration tests
[MAILPOET-6244]
2024-11-22 17:40:25 +01:00
8f3214b786 Update GitHub actions config
[MAILPOET-6244]
2024-11-22 17:40:25 +01:00
4ce3bd4b87 Update Circle CI config
[MAILPOET-6244]
2024-11-22 17:40:25 +01:00
8f2e17af93 Add installation of codeception into current install process
[MAILPOET-6244]
2024-11-22 17:40:25 +01:00
b992e93890 Update free integration tests
[MAILPOET-6244]
2024-11-22 17:40:25 +01:00
bbcaba86c4 Update PHPStan config to work with new location of Codeception
[MAILPOET-6244]
2024-11-22 17:40:25 +01:00
1ce32c47b4 Remove Codeception from free plugin deps
[MAILPOET-6244]
2024-11-22 17:40:25 +01:00
bbbc21a5d5 Update email-editor unit tests
We need to require autoload manually because codeception is no longer part of the package
[MAILPOET-6244]
2024-11-22 17:40:25 +01:00
85fad80a10 Update docker entry point for tests to use Codeception from root
[MAILPOET-6244]
2024-11-22 17:40:25 +01:00
51510216cc Remove codeception from email-editor package
[MAILPOET-6244]
2024-11-22 17:40:25 +01:00
8c2fdc173c Add codeception packages to tests_env
[MAILPOET-6244]
2024-11-22 17:40:25 +01:00
e74e1ef2a2 Register email patterns directly in plugin
[MAILPOET-6243]
2024-11-22 08:45:46 +01:00
5885077838 Register only email content email pattern category
As for now, pattern categories are hardcoded in the engine.
[MAILPOET-6243]
2024-11-22 08:45:46 +01:00
927a5e9464 Add checks for invalid data for patterns and categories
[MAILPOET-6243]
2024-11-22 08:45:46 +01:00
977876920b Update pattern hook names to align with other filters in editor
[MAILPOET-6243]
2024-11-22 08:45:46 +01:00
b52304179e Remove Cdn_Asset_Url class
[MAILPOET-6243]
2024-11-22 08:45:46 +01:00
b8147ed810 Remove pattern definitions from the editor package
[MAILPOET-6243]
2024-11-22 08:45:46 +01:00
a3f292f74e Register default patterns to the email editor via hooks
[MAILPOET-6243]
2024-11-22 08:45:46 +01:00
2409b5c8a1 Add default patterns into the MailPoet plugin integration
[MAILPOET-6243]
2024-11-22 08:45:46 +01:00
c06779acbb Introduce hooks for registering patterns for email editor
To get rid of hardcoded MailPoet-specific patterns from the editor package
We need to introduce an API to register the patterns and their categories.

Patterns have to be defined as extenders of Abstract_Pattern.

[MAILPOET-6243]
2024-11-22 08:45:46 +01:00
40ed694c02 Update k6 to 0.55 2024-11-21 11:59:59 +01:00
1a496ccc8d Remove unnecessary sleep 2024-11-21 11:59:59 +01:00
43198e4623 Add wait for page to load in login helper before navigating further 2024-11-21 11:16:02 +01:00
7781f46fcb Enforce direct FS_METHOD in tests to avoid FTP credentials issues
[MAILPOET-6244]
2024-11-20 22:28:39 +01:00
a59c93f811 Update templates version
[MAILPOET-6043]
2024-11-20 09:48:56 +01:00
d68e1c7960 Add Renderer class tests
[MAILPOET-6043]
2024-11-20 09:48:56 +01:00
97729b21ae Add Content Renderer test for blocks rendering
[MAILPOET-6043]
2024-11-20 09:48:56 +01:00
bee6d3a8aa Document test commands for editor package in readme.md
[MAILPOET-6317]
2024-11-19 15:34:00 +01:00
2341d8d0ce Release 5.4.0 2024-11-19 14:56:40 +01:00
78a3a51bab Fix WooCheckoutBlocks acceptance test 2024-11-18 17:42:57 +01:00
446a4284e0 Update used WooCommerce Subscriptions plugin in Circle CI
- latest version: 6.9.0
 - previous version: 6.8.0
2024-11-18 17:42:57 +01:00
0f576e50dc Update used Automate Woo plugin in Circle CI
- latest version: 6.1.1
 - previous version: 6.0.33
2024-11-18 17:42:57 +01:00
a560aeb890 Update used WordPress images in Circle CI
- latest version: 6.7.0-php8.3
 - previous version: 6.6.2
2024-11-18 17:42:57 +01:00
58f1af7920 Move Send_Preview_Email class to Engine folder and update tests
MAILPOET-6092
2024-11-18 15:28:31 +01:00
33031f3fbd Ensure up-to-date class-map autoload in GH actions tests
[MAILPOET-6092]
2024-11-18 15:28:31 +01:00
6fb8b6df2d Fix phpstan lint errors
MAILPOET-6092
2024-11-18 15:28:31 +01:00
5969e3438e Add and update tests for Send preview email
MAILPOET-6092
2024-11-18 15:28:31 +01:00
2216c065b2 Extend core email editor preview email functionality
With this commit, we override the core email editor send preview mail functionality with MailPoet version of the feature.

MAILPOET-6092
2024-11-18 15:28:31 +01:00
af29753c53 Move email preview filter method to email editor class. This fixes an issue with the method invocation
MAILPOET-6092
2024-11-18 15:28:31 +01:00
71a59f9f06 Add filter method to override email editor send preview mail functionality
MAILPOET-6092
2024-11-18 15:28:31 +01:00
d83c179f5c Fix code lint style errors
MAILPOET-6092
2024-11-18 15:28:31 +01:00
a9c2c3ca1d Add basic email sending support with wp_mail
MAILPOET-6092
2024-11-18 15:28:31 +01:00
ee967015dc Add Send_Preview_Email class for MailPoet email editor
MAILPOET-6092
2024-11-18 15:28:31 +01:00
87676ccdb6 Add base route for sending preview email
MAILPOET-6092
2024-11-18 15:28:31 +01:00
27d8093f86 Fix reCAPTCHA hardcode translated strings 2024-11-18 15:06:03 +01:00
5c398a3907 Remove unnecessary parenthesis 2024-11-18 15:06:03 +01:00
006b0b9c4f Reuse a helper method to check if Woo plugin active 2024-11-18 15:06:03 +01:00
974d8bc987 Fix JSON parsing error in reCAPTCHA validator 2024-11-18 15:06:03 +01:00
dc3b4855f2 Fix unverified test cases in reCAPTCHA renderer 2024-11-18 15:06:03 +01:00
1cb7221d5e Polishing reCAPTCHA validator unit tests 2024-11-18 15:06:03 +01:00
0cc1a1eb36 Refactor reCAPTCHA validation in MP forms
[MAILPOET-6282]
2024-11-18 15:06:03 +01:00
ba80233a3a Auto-format code in lib/Subscription directory 2024-11-18 15:06:03 +01:00
a23beba94f Fix invisible reCAPTCHA omit a field in form data
When users click the submit button that has both "name" and "value" attributes, the form data will include an extra field for the button.

Programmatic submissions omit this field because it doesn't trigger click event. Adjusting the logic to trigger click event will cause infinite recursion.

Omitting this field doesn't seem to disturb WP registration logic. Yet, for WC, it does.

[MAILPOET-6282]
2024-11-18 15:06:03 +01:00
aac6e936b9 Add ReCaptcha on WooCommerce registration form
[MAILPOET-6282]
2024-11-18 15:06:03 +01:00
5bf95b364b Add ReCaptcha on WordPress registration form
[MAILPOET-6282]
2024-11-18 15:06:03 +01:00
f5c996fe02 Ignore SpacesUsedHeredocCloser PHP code sniff
We prefer spaces over tabs. A parent sniff is already ignored: SpacesUsed.
2024-11-18 15:06:03 +01:00
7f91b69dcc Fix unresolved command in lint-staged-* for Linux
The 'source' command is not available in the default sh shell on Linux. The source command is specific to bash and other compatible shells. On Linux, the default sh shell is often dash, which does not support source. It seem to work on macOS because the default shell there is bash.

The . (dot) command is POSIX-compliant and works in both sh and bash.
2024-11-18 15:06:03 +01:00
f6befec2a2 Make email badge strings reusable by using placeholders
[MAILPOET-6312]
2024-11-18 14:07:19 +01:00
264bfd6ce7 Introduce and use a function for block editor page
This way, we don't need to search for the URL and edit it in multiple places.
[MAILPOET-6090]
2024-11-15 17:16:21 +02:00
6f53c159eb Simplify check for replacing editor
We always want to use the block email editor for mailpoet_email CPT.
We don't need to check if it is allowed for the CPT.
[MAILPOET-6090]
2024-11-15 17:16:21 +02:00
b124ffe596 Improve the comment about checking the editor page
[MAILPOET-6090]
2024-11-15 17:16:21 +02:00
33e828f2ed Remove the custom editor page
[MAILPOET-6090]
2024-11-15 17:16:21 +02:00
bc7bb56f90 Highlight the MailPoet > Emails menu item when editing email post
[MAILPOET-6090]
2024-11-15 17:16:21 +02:00
03686a09cd Update links to the email editor to go to post.php
[MAILPOET-6090]
2024-11-15 17:16:21 +02:00
cb78d98ad8 Improve detection that we are on the email editor page to cover also post editor
This is needed so that we can register some early hooks.
[MAILPOET-6090]
2024-11-15 17:16:21 +02:00
c71949e326 Render custom editor for mailpoet_email post types
[MAILPOET-6090]
2024-11-15 17:16:21 +02:00
f170db9294 Fix flaky ClickTest
This commit applies the fix that was made for testItUpdatesSubscriberTimestampsForHumanAgent
also to the other two test cases that suffer the same issue.
[MAILPOET-6322]
2024-11-15 12:41:33 +01:00
c7a93779f3 Update k6 tests and readme to fix the output issue
[MAILPOET-6321]
2024-11-15 12:27:44 +01:00
da5e90a429 Refactor .scss files import to one place
This approach is used in the Gutenberg repository.
Our original approach, where we imported styles in index files in subdirectories, was a bit fragile
because such a file might be skipped in case a component is imported directly.

[MAILPOET-6320]
2024-11-14 17:28:53 +02:00
67477dcc59 Fix flaky Statistics/Track/ClicksTest
The test was flaky because the assertion was sometimes missed by one second.
This commit reduces the flakiness by allowing a one-second difference when comparing the values.
[MAILPOET-6306]
2024-11-13 17:11:58 +01:00
7ae9c3028a Add migration for WooCommerce Subscription billing period field in automations
[PREMIUM-282]
2024-11-13 11:29:16 +01:00
7f7cd66d47 Add migration for WooCommerce Subscription status field in automations
[PREMIUM-282]
2024-11-13 11:29:16 +01:00
bc4e2375f3 Add comment why we strip WC order status prefix
[PREMIUM-282]
2024-11-13 11:29:16 +01:00
6f962d2112 Update used WooCommerce plugin in Circle CI
- latest version: 9.4.1
 - previous version: 9.3.3
2024-11-13 09:52:21 +01:00
f945ea8388 Use @wordpress/editor store with email editor components
MAILPOET-6303
2024-11-12 15:41:23 +01:00
e37997e2e1 Move ListviewSidebar state from email editor store to @wordpress/editor store
MAILPOET-6303
2024-11-12 15:41:23 +01:00
ef009d0400 Move InserterSidebar state from email editor store to @wordpress/editor store
MAILPOET-6303
2024-11-12 15:41:23 +01:00
990d82ef6c Return to PHP8.1 for wpcli_php_max_wporg
At this point it is still not possible to push PHP8.2 syntax to the repo.
I tested it with the readonly class syntax. We need to keep this job on PHP8.1
to make sure we don't add such a syntax.
[MAILPOET-4620]
2024-11-12 14:00:53 +01:00
2fcd27bb0b Update cookie check in acceptance tests for PHP8.2
In PHP 8.2 (or perhaps in 8.1, as we updated tests from 8.0),
there was a change that, when fetching from DB started returning
integers as integers, not strings as before.

This was causing the test to fail with PHP 8.2.
We were getting an error: 'Failed asserting that 2 is of type "string".'
We still support older PHP, so I fixed the issue by casting it back to a string.

[MAILPOET-4620]
2024-11-12 14:00:53 +01:00
985389830e Add a fix for the deprecation warning in Robo
This commit adds a fix to address a deprecation warning that is being printed in various Robo commands.
Deprecated: Creation of dynamic property Robo\Config\Config::$defaults is deprecated in /home/circleci/mailpoet/mailpoet/vendor/consolidation/robo/src/Config/Config.php on line 27

We can't update to the newer Robo version because we need to support PHP 7.4
[MAILPOET-4620]
2024-11-12 14:00:53 +01:00
dcc0c3cfd7 Switch test-env containers to PHP8.2
[MAILPOET-4620]
2024-11-12 14:00:53 +01:00
4faac92f6c Update dev-env to use PHP 8.2 as default
[MAILPOET-4620]
2024-11-12 14:00:53 +01:00
9a96e6aa92 Update Circle CI to use PHP 8.2 containers
[MAILPOET-4620]
2024-11-12 14:00:53 +01:00
9f366efa0d Release 5.3.7 2024-11-12 13:54:50 +01:00
ee401cfccc Add fallback for check indexExists in DbMigrator
This is a fallback for older DB versions when our approach with adding index does not exist because it returns different error.
[MAILPOET-6314]
2024-11-12 08:26:47 +02:00
ec54978e1b Add integration test for the DbMigration class
[MAILPOET-6314]
2024-11-12 08:26:47 +02:00
3fbff8c83f Optimize newsletter reactivation
When reactivating a newsletter with many queues (e.g., a welcome email with a long history)
NewsletterEntity::getQueues may fail because it attempts to fetch all queues and instantiate
many entity objects.

In this commit, I optimize this by looking only into unfinished queues.
getUnfinishedQueues look for where countToProcess is higher than 0.
We set the count for welcome emails when we create a new queue
see f1ffc77bf3/mailpoet/lib/Newsletter/Scheduler/WelcomeScheduler.php (L140)
[MAILPOET-6310]
2024-11-11 12:21:22 +01:00
1c3ea9cd0a Move email editor components out of the engine folder
MAILPOET-6215
2024-11-11 11:53:49 +02:00
e6d607028c Move powered by mailpoet block back to the main mailpoet assets folder
MAILPOET-6215
2024-11-11 11:53:49 +02:00
716ba4ebc3 Fix typescript and type check errors
MAILPOET-6215
2024-11-11 11:53:49 +02:00
b37fd8aa6a Update git blame commit hash for email editor prettier autoformatting
MAILPOET-6215
2024-11-11 11:53:49 +02:00
8c604453b1 Run email editor through Prettier
MAILPOET-6215
2024-11-11 11:53:49 +02:00
3402ae74da Add Prettier support for WP coding style
MAILPOET-6215
2024-11-11 11:53:49 +02:00
8c8bd728a7 Update git blame commit hash
MAILPOET-6215
2024-11-11 11:53:49 +02:00
ef4cf077ba Ensure linting is done for email editor JS and CSS files
MAILPOET-6215
2024-11-11 11:53:49 +02:00
820cbd2939 Fix wp-scripts lint errors
MAILPOET-6215
2024-11-11 11:53:49 +02:00
a6e6e30a56 Fix Prettier conflict with WP coding style by ignoring email editor js package
There's a custom Prettier package we can use for the email editor package and a custom config `@wordpress/prettier-config` available

MAILPOET-6215
2024-11-11 11:53:49 +02:00
b2fb96f879 Switch email editor js package to WP coding style
MAILPOET-6215
2024-11-11 11:53:49 +02:00
462434af5d Fix email editor css link
MAILPOET-6215
2024-11-11 11:53:49 +02:00
fed306490a Fix webpack build and compile
MAILPOET-6215
2024-11-11 11:53:49 +02:00
e8180fcbc5 Convert named alias to relative paths.
This seems to be having an issue with the current webpack config and the babel loader. We will fix the issue on another ticket

MAILPOET-6215
2024-11-11 11:53:49 +02:00
632c381b73 Add basic email editor build config
MAILPOET-6215
2024-11-11 11:53:49 +02:00
f787e6d98c Update git blame ignore
MAILPOET-6215
2024-11-11 11:53:49 +02:00
912282f57c Move all items to src folder
MAILPOET-6215
2024-11-11 11:53:49 +02:00
1f85d1586d Add commit to git blame ignore
This excludes the mass file movement from git blame

MAILPOET-6215
2024-11-11 11:53:49 +02:00
466b9c1235 Move email editor to JS packages folder
MAILPOET-6215
2024-11-11 11:53:49 +02:00
3d312953b3 Update symfony/process
I added symfony/process to compose.json to be able to install version 5.4.46.
Without this restriction composer installed 5.4.x-dev which I didn't want to use
as the version name suggests it is not stable.
[MAILPOET-6313]
2024-11-08 19:45:31 +01:00
9cb19b06c1 Update symfony/validator and symfony/translations
We needed to update the validator, but I had to update also translations
to workaround dependency conflict issues.
[MAILPOET-6313]
2024-11-08 19:45:31 +01:00
20d9db6f42 Update twig
[MAILPOET-6313]
2024-11-08 19:45:31 +01:00
0d94f42452 Fix typo in CodeSniffer config
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
ff1ff230e2 Change cache keys for dependencies in email editor GH action
Because we changed the file names the PSR-4 loading does not work, but this loading is changed. I changed the key to avoid failing test workflows.
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
5c05a56669 Add a new job with Code style into email editor GH action
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
9d65e2dbe8 Deactivate the rule about file_get_contents
I temporarily deactivated the rule because the change can be more complex.
WP_Filesystem cannot be used because we load files in constructors.
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
de12dbbb22 Add email-editor into prettier ignore list
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
65948c8033 Add mock esc_html into unit test bootstrap
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
853bf6fcfe Migrate integration tests in Integrations directory to WordPress Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
e69666776d Migrate integration tests in Engine directory to WordPress Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
0c781be938 Migrate integration tests bootstrap file to WordPress Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
c6f6eeef53 Add excluded rule for tests to avoid repetition
Our tests use method _after and _before, so we would need to add ignore to each usage.
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
d0c8cde59c Migrate tests/unit folder to WordPress Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
d0f8d6f83e Migrate tests/unit/Integrations folder to WordPress Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
906e80a6d7 Migrate tests/unit/Engine folder to WordPress Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
be63af8102 Migrate tests/_support folder to WordPress Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
113dbaae2d Change coding style in email editor tests to WordPress
This commit contains automated changes made with phpcbf command from CodeSniffer package.

[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
8d7f26c42d Add CodeSniffer config file based on WordPress standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
9f08c1864c Update .editorconfig to prefer tabs in email-editor package folder
WordPress coding standard use tabs, so this can help developers to work more confidently.
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
ef8f122bb7 Migrate email editor Validator to WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
fc7e06730b Migrate email editor dom document helper class to WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
eccf8ce0a2 Migrate email editor core initializer class to WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
d82f8ea9fa Migrate email editor Core block render classes to WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
e850028a1c Migrate email editor cdn-asset-url class to WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
5ad66a7db6 Migrate last email editor files from engine to WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
9653fc756b Migrate email editor contentRenderer classes from to WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
6e2a2d4b7e Migrate email editor preprocess files to WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
ef6ecb8159 Migrate email editor postprocessor files to WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
df6f7198a6 Migrate email editor flex-layout-renderer class to WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
f5e54abecf Migrate email editor templates class to WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
a31857ffee Migrate email editor template-preview class to WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
0a105dbe81 Migrate email editor utils class to WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
f050020d67 Migrate email editor classes Engine\Patterns directory to WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
062f504e14 Migrate email editor email-editor to WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
37b3cfbbc2 Migrate email editor email-api-controller to WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
734b70489d Migrate email editor email-styles-schema to WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
c83ec3c8d7 Migrate email editor settings-controller to WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
fba5482cd2 Migrate email editor theme-controller to WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
ecbd2f150d Migrate email editor Contaienr to WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
554adccce3 Change coding style in email editor package to WordPress
This commit contains automated changes made with phpcbf command from CodeSniffer package.
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
b6103b4581 Rename files in email editor package by WP Coding Standard
[MAILPOET-6240]
2024-11-08 14:06:45 +01:00
46fb372008 Fix the analytics page when automation has if/else without next steps
The code if/else handling empty next steps on a branch was relying on a sibling step.
In case the if/else had no next steps on both branches, it threw an error and broke the app.
[MAILPOET-6307]
2024-11-06 10:29:07 +01:00
84d3de7f6a Remove unnecessary block enhancer
We disabled margin globally in the theme.json file. We don't need to disable the option at block level again.

MAILPOET-6237
2024-11-05 19:35:34 +01:00
4f3209b670 Remove unnecessary renderer block
We don't need a special renderer for the spacer block as the fallback renderer can handle its functionality

MAILPOET-6237
2024-11-05 19:35:34 +01:00
d9fa9cd18a Disable margin style for spacer block.
The renderer currently does not support the Margin property.

MAILPOET-6237
2024-11-05 19:35:34 +01:00
ad58f6213e Add Spacer block support
MAILPOET-6237
2024-11-05 19:35:34 +01:00
71f3b07c61 Release 5.3.6 2024-11-05 13:48:43 +01:00
7b750ece51 Update readme documentations
MAILPOET-6255
2024-11-05 09:09:44 +01:00
657c8ea3ad BFCM 2024 sale
[MAILPOET-6284]
2024-11-04 22:12:06 +01:00
1c3d02e58d Insert the link into the footer if it is present
[MAILPOET-6254]
2024-11-04 13:24:29 +01:00
d306e477cb Remove debounce from validation
Debounce caused trouble because after clicking the function
renders multiple times. First with the invalid content and
then with the right content with the link present.
With debounce the test was not run for the content with the
link.

[MAILPOET-6254]
2024-11-04 13:24:29 +01:00
00801f7573 Remove global variable
[MAILPOET-6254]
2024-11-04 13:24:29 +01:00
29aa93318c Move rules inside action
[MAILPOET-6254]
2024-11-04 13:24:29 +01:00
63bb136be6 Fix the action to add unsubscribe link
[MAILPOET-6254]
2024-11-04 13:24:29 +01:00
4039824580 Fix race condition
[MAILPOET-6304]
2024-11-04 13:58:59 +03:00
58f1c7d915 Test UserAgentRepository
[MAILPOET-6304]
2024-11-04 13:58:59 +03:00
3a197c129e Flush immediatly
[MAILPOET-6304]
2024-11-04 13:58:59 +03:00
304e4f78c3 Separate finding and creation of user agent
Will help later with testing

[MAILPOET-6304]
2024-11-04 13:58:59 +03:00
bb1a5e08aa Fix acceptance test for the email editor
I din't find a better way to fix it. For some reason, the switching to iframe was not working
properly executed immediately when the iframe was spotted.
[MAILPOET-6280]
2024-11-04 11:30:35 +01:00
e77f075d75 Fix border-radius support in the group block.
[MAILPOET-6280]
2024-11-04 11:30:35 +01:00
2d0621d386 Render caption html conditionally
In case the image has no caption we don't need to render the markup wrapping the caption.
[MAILPOET-6280]
2024-11-04 11:30:35 +01:00
9829c96caa Add border support to the image renderer
This commit fixes how the border is applied in an image block.
- the border is applied to the wrapping table cell instead of the image
- we need to move classes related to border styles to the cell so that related styles are inlined in the proper place
- the caption is put in an additional table so that it doesn't extend the border when it is longer than the image
- rounded image styles are now applied to the wrapper and the image
[MAILPOET-6280]
2024-11-04 11:30:35 +01:00
10ad46239d Fix border rendering on mobiles for columns
[MAILPOET-6280]
2024-11-04 11:30:35 +01:00
5044f8f276 Add border support for paragraph and heading blocks
[MAILPOET-6280]
2024-11-04 11:30:35 +01:00
b83ecbbe70 Disable margin globally
We don't support margin in the renderer.
[MAILPOET-6280]
2024-11-04 11:30:35 +01:00
df350427ed Fix UI issues in the editor in WP6.7
[MAILPOET-6280]
2024-11-04 11:30:35 +01:00
483639713f Minor performance improvements: cache and reduce WP translate function call
MAILPOET-6298
2024-10-31 15:54:28 +02:00
86fb7f2cdb Fix failing test
MAILPOET-6298
2024-10-31 15:54:28 +02:00
6ea5074649 Move WP translation function from __construct
According to this post https://make.wordpress.org/core/2024/10/21/i18n-improvements-6-7/, we are currently doing_it_wrong

MAILPOET-6298
2024-10-31 15:54:28 +02:00
1f21add146 Add skip-plugins support for acceptance tests
MAILPOET-6298
2024-10-31 15:54:28 +02:00
d13c2a82e2 Ensure translation is not loaded when fetching woocommerce version
MAILPOET-6298
2024-10-31 15:54:28 +02:00
7259d8cda2 Release 5.3.5 2024-10-30 19:22:45 +03:00
c80416a802 Use post_date_gmt instead of post_date
This commit ensures we are querying posts after a UTC date.

[MAILPOET-6234]
2024-10-30 18:03:04 +03:00
d00ba69fb3 Test that the correct post is fetched
This test ensures we are comparing the right dates against each other when fetching posts.
We used to compare a UTC time against post_date, which represents the publication date of
the post in the local timezone.

[MAILPOET-6234]
2024-10-30 18:03:04 +03:00
fbd9d9ba83 Release 5.3.4 2024-10-29 15:28:02 +02:00
8dcb2ef3d2 Add bool type cast to the return value
MAILPOET-6299
2024-10-29 01:45:49 +03:00
a511307305 Make sure the running tasks are paused
[MAILPOET-6259]
2024-10-28 11:09:57 +01:00
55f21e8cd7 Fix inactive notifications clog sending queue
[MAILPOET-6259]
2024-10-28 11:09:57 +01:00
3f6ca7517a Fix unit tests and potential ensure email_attrs being set
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
8c1c6f1136 Update email content validation to look also in template code
The unsubscribe link might be present in template so we need to
look in both email and template.
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
c2ef0ac2ea Remove EMAIL_WIDTH constant from SettingsController
Email width is set in theme JSON so this was a duplicity.
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
85da4d0659 Adjust renderer tests to cover styles added to wrapper
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
e3d5b7a7e0 Disable block gap rendering between root-level blocks.
Top level blocks are post content and header and footer wrapping blocks.
Disabling the gap between these blocks prevents rendering a gap between
post-content blocks and header and footer.
[MAILPOET-6088]
2024-10-25 17:47:58 +02:00
4a04744d1c Use default layout in general template
The default layout disables align-full, which is now not supported.
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
77455c6e42 Use different patterns for the general email template and the rest
The general email template is a blank template without a header and footer.
This commit reintroduces the content pattern with a header and footer content
and uses it as the default for the general template.

[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
355c144dc9 Simplify the DefaultContent pattern
This removes the header and footer from the content pattern.
The header and footer should be part of the template
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
f842ed4b33 Remove old demo templates
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
2a251e70f7 Add a new template with more meaningful content
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
324fedecbf Get rid of duplicate CSS for template preview
We can reuse the same CSS we pass to editor
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
b6d75410cf Render proper content width in template previews
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
801f586b00 Prevent block gap for list item
The list item gets spacing via the fallback renderer.
To prevent this, I created a renderer that skips spacing.
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
af0b4f37bc Add class for detection of text blocks
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
95f7049bd9 Introduce file for sharing CSS for content between editor and renderer
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
b87eb3edd3 Remove unused CSS for alingfull for post content
The align full is currently disabled and the CSS was working only for the hardcoded value.
Probably a leftover from some testing
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
000bbd993b Move styles for content in email editor to one place
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
1c2078d698 Remove unnecessary CSS code for global padding
The top and bottom padding seems to be generated properly on the client side.
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
7b6bf1f4b4 Remove srcset from images
The srcset breaks the rendering of images in some clients (observed on iOS and MacOS clients in Email on Acid tester).

[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
7bef08f7e1 Fix email width in desktop Outlook
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
254e598627 Fix columns rendering for Gmail and desktop Outlook
The issue was that the code for block spacing was wrapping the column into an additional div and conditional table.
We don't need spacing for columns as they are rendered side by side, and the spacing is applied to the wrapping columns block.
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
0c87131812 Fix that horizontally aligned image breaks mobile rendering
We set the width to wrappers of horizontally aligned images to have correctly positioned captions.
We need to resize these wrappers on mobile otherwise, they keep the width and make the email wider than the screen.
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
5c1796eb2a Apply global padding on wrapper in renderer
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
d949f2ce1b Fix block spacing for group blocks
This is the same fix that we applied for the column block
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
cf47919d53 Fix mobile preview styles in the editor
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
efa290c41c Add comment to CSS for border-box for columns
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
b0507bca9e Fix alignment and block gap settings for columns and groups
In this commit, I disabled the layout for both groups and columns.
This allows using our custom css for alignment of images (left, right and center).
The CSS for constrained layout uses floats and it breaks spacing in the editor.
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
e9d6658b20 Add configuration for alignment options for blocks.
This configuration allow none, left, center and right alignment options
for blocks in containers with default layout.
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
224eb51b25 Unify padding rendering between editor and renderer
This commit removes "padding bubbling" to children.
The bubling was added because of full width alignment.
The full aligment is currently not supported and this bubbling was causing issues with rendering multiple paddings.
The main padding is applied around the content.
[MAILPOET-6249]

# Conflicts:
#	mailpoet/assets/js/src/email-editor/engine/components/block-editor/visual-editor/visual-editor.tsx
#	packages/php/email-editor/src/Engine/SettingsController.php
2024-10-25 17:47:58 +02:00
3ef305facd Simplify the VisualEditor component
We don't support post-only mode for emails, so I was able to remove
more core related to that mode.
The post-only mode is used in the template-mode, but it is a designPostType
so the code was not used anyway.
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
60525198c5 Always replace vars when getting email styles
We use the styles in preprocessors, so we always need to access
values (e.g. spacing) instead of variables.
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
a40eb3e554 Respect layout content size set in theme.json in the renderer
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
06067b36f6 Introduce ThemeController::getLayoutSettings()
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
fca191c6f4 Remove layout settings from the editor state
The layout is set in theme JSON and passed via editor settings
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
cec9175c5d Make sure all compressed vars are decompressed when getting theme styles
The previous implementation was keeping compressed vars (e.g. var:preset|spacing|10)
in styles settings and value replacing was able to process only
those prefixed var|preset|color.
This refactor adds extraction of all compressed values to valid css variables,
which can be replaced immediately or later by variables postprocessor.
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
84dab903d7 Fix layout block-gap settings to be applied to all blocks
Prior this change it was not applied to blocks that have no
renderer registered.
The block gap rendering is added applied in AbstractBlockRenderer
so adding a Fallback renderer that extends the AbstractBlockRenderer
for all blocks that don't have specific renderer solves the issue.
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
45eeadf000 Use fixed layout width in editor
The settings in theme prevent users from changing layout and it's width in UI.
[MAILPOET-6249]
2024-10-25 17:47:58 +02:00
3a92f0b0fd Update unit tests
[MAILPOET-3729][MAILPOET-6204][MAILPOET-6205]
2024-10-24 11:43:19 +02:00
e5df29901e Update integration tests
[MAILPOET-3729][MAILPOET-6205]
2024-10-24 11:43:19 +02:00
0c4561b8f6 Improve accessibility by linkin <label> with <input> on checkboxes and radios
[MAILPOET-3729][MAILPOET-6205]
2024-10-24 11:43:19 +02:00
3fe98bc238 Improve accessibility by marking required fields also for screen readers
[MAILPOET-6204]
2024-10-24 11:43:19 +02:00
2c7577b315 Improve labels accessibility for public forms
[MAILPOET-6204]
2024-10-24 11:43:19 +02:00
15b63a6794 Simplify code
[MAILPOET-6204]
2024-10-24 11:43:19 +02:00
484b212b17 Remove unnecessary message (already defined above)
[MAILPOET-6204]
2024-10-24 11:43:19 +02:00
1c89b40b85 Unify checking if block is required
[MAILPOET-6204]
2024-10-24 11:43:19 +02:00
f0bcd3ef01 Unify getting block label
[MAILPOET-6204]
2024-10-24 11:43:19 +02:00
069ef1cb2b Release 5.3.3 2024-10-22 20:32:17 +02:00
164cb290ec Move newsletter stats translaton inside a function
The reason is, that translation strings outside any function weren't translated at all, even if they are present in .pot

[MAILPOET-6296]
2024-10-22 19:17:43 +02:00
c98fd2a091 Revert "Move newsletter stats translaton inside component"
This reverts commit 2bc29c8b0a.
2024-10-22 19:17:43 +02:00
0e04dc015c Release 5.3.2 2024-10-22 15:12:33 +02:00
d1d306a224 Fix spacing when too long period message is shown
[MAILPOET-6295]
2024-10-22 14:12:53 +02:00
da728af4d9 Switch re-engagement setup from single row to two rows
This helps accommodate longer translations

[MAILPOET-6295]
2024-10-22 14:12:53 +02:00
86d7ce2119 Include "
[MAILPOET-6292]
2024-10-21 14:57:49 +02:00
42e88ee78c Add stub
[MAILPOET-6292]
2024-10-21 14:57:49 +02:00
6e9fcf6621 uses kses
[MAILPOET-6292]
2024-10-21 14:57:49 +02:00
0fd1fba20d Early return when rules are empty
[MAILPEOT-6292]
2024-10-21 14:57:49 +02:00
239955fc36 Improve rendering of parsley attributes
[MAILPOET-6294]
2024-10-21 14:57:49 +02:00
3b68ab0311 Avoid to code repetition
[MAILPOET-6294]
2024-10-21 15:54:02 +03:00
75e5c3c229 Update Date unit test
[MAILPOET-6294]
2024-10-21 15:54:02 +03:00
be1c2f20ba Improve Date translation custom fields
[MAILPOET-6294]
2024-10-21 15:54:02 +03:00
c015092133 Reintroduce the client-side filtering of email templates
We still need to filter the templates because, in some cases, the API also returns custom templates
ignoring the post_type filter in the query
[MAILPOET-6279]
2024-10-21 14:13:10 +02:00
1626ded39a Use post_type parameter to filter email-related templates
This commit utilizes the post_type parameter that ensures that the REST API returns
only the templates associated with the specified post type.
It improves performance because before the change we were fetching all existing templates and filtering them on client.
[MAILPOET-6279]
2024-10-21 14:13:10 +02:00
428a5e1fe7 Update used WooCommerce Subscriptions plugin in Circle CI
- latest version: 6.8.0
 - previous version: 6.7.0
2024-10-21 12:21:27 +02:00
c661bdd7f8 Remove port for testing container 2024-10-21 12:38:21 +03:00
52f88601a4 Use a different port for testing in order
We need to prevent a conflict with the dashboard
2024-10-21 12:38:21 +03:00
3e27192f83 Move fix for missing confirmation email hash to migrations
[MAILPOET-6273]
2024-10-21 11:25:13 +02:00
d7acf7b34d Add hash to the newsletter when creating
[MAILPOET-6273]
2024-10-21 11:25:13 +02:00
3d2ad79931 Ensure the newsletter has hash before preview
[MAILPOET-6273]
2024-10-21 11:25:13 +02:00
9aacac0743 Improve anchor rendering in the heading block
[MAILPOET-6290]
2024-10-21 11:23:43 +02:00
af1a94ffcd Improve rendering of heading tag
[MAILPOET-6291]
2024-10-21 11:23:43 +02:00
f002af43b0 Fix fieldLabel used in attribute
[MAILPOET-6293]
2024-10-21 11:33:25 +03:00
2bc29c8b0a Move newsletter stats translaton inside component
The reason is, that translation strings outside weren't translated at all, even if they are present in .pot

[MAILPOET-6262]
2024-10-18 13:58:59 +02:00
6a8a209d11 Use correct translation function
[MAILPOET-6262]
2024-10-18 13:58:59 +02:00
ebcfca9a56 Fix CustomHtml block class
[MAILPOET-6287]
2024-10-18 13:39:41 +02:00
c3df5d4685 Fix CustomHtml block
[MAILPOET-6287]
2024-10-18 10:50:34 +02:00
7d7b549a56 Update selector in reengagement test 2024-10-17 20:00:32 +02:00
43f95d21fd Unify focus states in <Checkbox>, <Radio>, <Toggle>, and <YesNo> components
[MAILPOET-4546]
2024-10-17 13:59:53 +02:00
712481c426 Make <Toggle> and <YesNo> components focusable
[MAILPOET-4546]
2024-10-17 13:59:53 +02:00
fd9b73e323 Revert Readme prettier fix 2024-10-17 12:24:28 +02:00
6a61ae9ceb Prettier fix 2024-10-17 12:24:28 +02:00
db1038aab0 Update performance tests 2024-10-17 12:24:28 +02:00
cf9366285b Change form error messages font-size from px to rem
0.8rem is roughly the same as 13px in WordPress admin (which is set to 16px). On frontend, it will depend on theme's setting, so it might differ in practice, but to keep it somewhat consistent, the error message is smaller than default website font-size.

[MAILPOET-6203]
2024-10-16 12:20:34 +02:00
0505f1c123 Only allow positive numbers in re-engagement period setup
[MAILPOET-6266]
2024-10-16 11:18:09 +02:00
ad355533ac Add missing translations
[MAILPOET-6266]
2024-10-16 11:18:09 +02:00
9d905f2fd1 Fix re-engagement setup layout
[MAILPOET-6266]
2024-10-16 11:18:09 +02:00
8020f28d23 Release 5.3.1 2024-10-15 12:56:11 +02:00
8abb03ae83 Prevent a warning if caption is not present
[MAILPOET-6261]
2024-10-14 14:43:18 +02:00
48e267f6ec Update PHP 8.2 deprecations fix for html2text
[MAILPOET-6258]
2024-10-14 14:00:33 +02:00
45cf86fc75 Use cached authorized emails when API is down 2024-10-14 13:30:16 +02:00
8f95229288 Remove no longer used class parameter 2024-10-14 13:30:16 +02:00
73e8ad717d Use controller over service to get authorized emails
A preliminary step to enable caching authorized emails data from the API
2024-10-14 13:30:16 +02:00
32cd4c36dd Strip service method to return raw responses
A preliminary step to enable caching authorized emails data from the API
2024-10-14 13:30:16 +02:00
f39339a7ac Fix IDE force new line after class brace
Since it's not defined in EditorConfig, IDE will use the default setting, or user setting (defined in .idea dir), if overridden!
2024-10-14 13:30:16 +02:00
f88810beeb Change WordPress port in Docker Compose for testing
On Linux, 8080 port is used by A8C proxy (in the PAC file), and it's hard to change
2024-10-14 13:30:16 +02:00
527e7aa29b Fix deprecation warning in authorized email controller 2024-10-14 13:30:16 +02:00
324a10186a Minor refactorings in bridge API service 2024-10-14 13:30:16 +02:00
b3530adf77 Remove unused constant in bridge API service 2024-10-14 13:30:16 +02:00
ef91d4a8f2 Fix husky deprecation in pre-commit hook
Fixes this error: please remove the following two lines from .husky/post-checkout:

. "$(dirname -- "$0")/_/husky.sh"

They WILL FAIL in v10.0.0
2024-10-14 13:30:16 +02:00
339260d809 Fix integration test
[MAILPOET-6264]
2024-10-14 13:01:20 +02:00
bcc562eb4b Add migration to remove Google+ icons from existing templates
[MAILPOET-6264]
2024-10-14 13:01:20 +02:00
5f633c63b9 Remove Google+ social icons from email templates
[MAILPOET-6264]
2024-10-14 13:01:20 +02:00
1233525d5f Add max-width for email preview templates
[MAILPOET-6265]
2024-10-09 23:19:13 +03:00
a6fa0c8780 Make re-engagement period value required and number only
[MAILPOET-6267]
2024-10-09 23:08:55 +03:00
98ff6eb3bb Update used WooCommerce plugin in Circle CI
- latest version: 9.3.3
 - previous version: 9.2.3
2024-10-07 18:22:27 +03:00
a0b9b2acd3 Release 5.3.0 2024-10-03 15:02:43 +02:00
eb71f3d7fb Make the zip build wait for all jobs 2024-10-03 13:37:36 +02:00
714d8da93a Fix timestamp values in SendingQueue and Statistics repository
This commit fixes a few more occurences of incorrect time being saved in the DB.
We need to use UTC.

[MAILPOET-6260]
2024-10-03 12:42:00 +02:00
b680dc4f6d Fix the abandoned cart scheduling mechanism
We need to use GMT time when we save timestamps to the DB.
The scheduled task was using site's time, and it could cause delay of the trigger in UTC- zones or run it too early and cause email not being sent in UTC+ zones.

[MAILPOET-6260]
2024-10-03 12:42:00 +02:00
63a153dcd5 Flatten build 2024-10-03 12:31:46 +02:00
da1fb4ba5f Release 5.2.3 2024-10-01 15:33:49 +03:00
e5848d08b3 Preserve normal text wrapping in email editor
[MAILPOET-6250]
2024-10-01 10:12:01 +03:00
885533660f Improve typography by using pretty and balanced text-wrap
[MAILPOET-6250]
2024-10-01 10:12:01 +03:00
6e5e23cbb7 Add acceptance test for automation analytics stats in the flow with if/else steps included
[MAILPOET-6230]
2024-09-30 12:36:07 +02:00
70800589d0 Use constants
[MAILPOET-6230]
2024-09-30 12:36:07 +02:00
f69d557fe4 Correctly mark steps as completed when if/else branch are present
We can't mark all steps as completed, because the user would only go in one of the branches

[MAILPOET-6230]
2024-09-30 12:36:07 +02:00
9dbb33a8ae Add if/else step to Automation data factory
[MAILPOET-6230]
2024-09-30 12:36:07 +02:00
7fdd4fd9d7 Correctly calculate empty if/else branch stats
[MAILPOET-6230]
2024-09-30 12:36:07 +02:00
274d3ea297 Calculate step separator stats based on next step and not previous one
When considering previous step, in if/else step it always returned the same value for both branches because it took stats from the main if/else step and not from the each branch's steps.

[MAILPOET-6230]
2024-09-30 12:36:07 +02:00
7b84b93fbf Pass next step to flow separator
[MAILPOET-6230]
2024-09-30 12:36:07 +02:00
696d448604 Rename step_data.flow to better describe what it represent
[MAILPOET-6230]
2024-09-30 12:36:07 +02:00
fd18bee9d8 Update k6 and its dependencies 2024-09-25 16:06:54 +02:00
6bc9e3da19 Replace deprecated Query with direct access to DataStore
Automattic\WooCommerce\Admin\API\Reports\Customers\Stats\Query is deprecated and the recommendation is to access DataStore directly, which is what Query would do previously

[MAILPOET-6253]
2024-09-25 10:52:51 +02:00
4d0e0e6ee6 Don't generate SCSS source maps in release build
[MAILPOET-6247]
2024-09-24 18:38:36 +02:00
8a9680120c Update new email editor acceptance tests to run with WP6.6 and above
[MAILPOET-6105]
2024-09-24 12:07:24 +02:00
6af7711e3a Update schema version in the core integration
[MAILPOET-6105]
2024-09-24 12:07:24 +02:00
85c028f6b1 Fix positioning of email content
This was overwriting the margin: 0 auto; and was causing the content
not being properly centered in canvas.
[MAILPOET-6105]
2024-09-24 12:07:24 +02:00
9bec9c9e33 Update classes of inserter sidebar
[MAILPOET-6105]
2024-09-24 12:07:24 +02:00
a35a1dccbf Fix positioning of the spinner on editor startup
[MAILPOET-6105]
2024-09-24 12:07:24 +02:00
ac6474d809 Let the visual editor component handle preview on devices
[MAILPOET-6105]
2024-09-24 12:07:24 +02:00
3b81924625 Reintroduce support for default font sizes
[MAILPOET-6015]
2024-09-24 12:07:24 +02:00
b4219eb6fe Fix the appearance of tools in the header and list view sidebar
[MAILPOET-6105]
2024-09-24 12:07:24 +02:00
d608e8c066 Fix top vs inline block toolbar setting in more menu
[MAILPOET-6105]
2024-09-24 12:07:24 +02:00
e7dd854bbb Fix fetching patterns for editor
[MAILPOET-6105]
2024-09-24 12:07:24 +02:00
f8d990863c Fix inserter sidebar close button
[MAILPOET-6105]
2024-09-24 12:07:24 +02:00
a4d0361f37 Add simplified visual editor component
This is a copy of a compoponent from wordpres/editor package.
I tried to remove as much as possible to make it easier to read.
There is a known issue with layout that we don't suppport Align property properly.§
[MAILPOET-6105]
2024-09-24 12:07:24 +02:00
69e7b543dc Update private APIs unlock optin message to match wp6.6
[MAILPOET-6105]
2024-09-24 12:07:24 +02:00
048f3cfbc1 Release 5.2.2 2024-09-24 11:54:37 +02:00
ce75318f8b Fix linting error that only happens on CI
[MAILPOET-4326]
2024-09-23 16:08:16 +02:00
d586694cea Customize hints for form placement
This changes the hint that we display to help customers place a
subscription form on their website. Not all themes support widgets, but
not all themes support FSE either.

[MAILPOET-4326]
2024-09-23 16:08:16 +02:00
cd5386825f Expose theme support feature to TS
[MAILPOET-4326]
2024-09-23 16:08:16 +02:00
50b48267cc Expose WP theme features in form editor
[MAILPOET-4326]
2024-09-23 16:08:16 +02:00
457c16e5f8 Use site-editor to configure widget forms
We used widgets.php previously, but not all themes support widgets.

[MAILPOET-4326]
2024-09-23 16:08:16 +02:00
37a9c4e32e Fix List-Unsubscribe URL for non-MSS methods when tracking enabled
Previously, we were using the value of $extraParams['unsubscribe_url'],
which points to a tracking link when tracking is enabled. However, with
1-click unsubscribe, redirects are not allowed.
2024-09-23 16:01:40 +02:00
a4e063f8fc Improve annotation in EmailEditor\Container
[MAILPOET-6216]
2024-09-23 15:16:59 +02:00
7a793f11f1 Remove redundant methods from email editor IntegrationTester
[MAILPOET-6216]
2024-09-23 15:16:59 +02:00
d6b3ebddb8 Add GitHub action for email editor tests
[MAILPOET-6216]
2024-09-23 15:16:59 +02:00
8dc9c28fdf Fix namespace in integration tests
This commit also removed the redundant directory EmailEditor from integration tests directory.
[MAILPOET-6216]
2024-09-23 15:16:59 +02:00
99a6541ffb Fix namespace in unit tests
[MAILPOET-6216]
2024-09-23 15:16:59 +02:00
246a10f058 Copy Validator to email-editor package
Because the email-editor package should be independent. We copy Validator to the package, at least for now.
[MAILPOET-6216]
2024-09-23 15:16:59 +02:00
b2e8a9c82b Remove usage of constant from NewsletterEntity
[MAILPOET-6216]
2024-09-23 15:16:59 +02:00
45a8233a1e Copy CdnAssetUrl to email-editor package
For independence of the email-editor package, I copied the class to the package.
[MAILPOET-6216]
2024-09-23 15:16:59 +02:00
4424a33624 Add Container class
This class is used as DI Container for easier injecting classes in integration tests.
It can be also reused during a standalone usage.
[MAILPOET-6216]
2024-09-23 15:16:59 +02:00
1af3c09422 Bootstrap email-editor integration tests
I tried to minimize the code repetition.
[MAILPOET-6216]
2024-09-23 15:16:59 +02:00
d38e6bb1b9 Bootstrap email-editor unit tests
I also replaced using verify function by asserts, which will be removed in the higher version of phpunit.
[MAILPOET-6216]
2024-09-23 15:16:59 +02:00
98712db36d Add composer files for email-editor package
[MAILPOET-6216]
2024-09-23 15:16:59 +02:00
d0c1ad4aba Move email editor integration tests
[MAILPOET-6216]
2024-09-23 15:16:59 +02:00
0860f7c45f Move email editor unit tests
[MAILPOET-6216]
2024-09-23 15:16:59 +02:00
09a8d7445b Use composer env variable for copying local packages
[MAILPOET-6216]
2024-09-23 15:16:59 +02:00
9c926fd99f Update composer.json and docker-compose.yml
[MAILPOET-6216]
2024-09-23 15:16:59 +02:00
ea71b6c967 Move EmailEditor PHP files into a packages directory
[MAILPOET-6216]
2024-09-23 15:16:59 +02:00
fe4eeb0049 Fix send email step time-out happening too early
This was an off-by-one error — the first step run is the email scheduling run.

[MAILPOET-6246]
2024-09-23 13:00:48 +02:00
e609adf408 Update used WooCommerce plugin in Circle CI
- latest version: 9.3.2
 - previous version: 9.2.3
2024-09-23 08:53:41 +02:00
0198eae41a Update WC action when setting cart item to zero
[MAILPOET-6069]
2024-09-23 08:32:06 +02:00
a90997ea1f Remove spacing in test and update code 2024-09-18 09:44:13 +02:00
8fa109571f Fix php linting 2024-09-18 09:44:13 +02:00
ce0937b880 Update tests to add subscriber and stats page newsletter timezone check 2024-09-18 09:44:13 +02:00
a085b76b4c Update existing schedule newsletter test to include timezone scenario 2024-09-18 09:44:13 +02:00
70b4602e94 Release 5.2.1 2024-09-18 09:34:16 +02:00
981e64b57f Remove deprecated version from docker-compose file
[MAILPOET-6233]
2024-09-18 07:52:26 +02:00
1a0fecf2db Rename docker-compose to docker compose
[MAILPOET-6233]
2024-09-18 07:52:26 +02:00
0efe8e0204 Set no-cache headers for pulic MailPoet router
This includes open and click tracking, cron daemon, view in browser,
form previews, subscription management, and image proxy for thumbnails.
2024-09-17 17:27:37 +02:00
38c6880400 Unify setting no-cache headers, use WP-native nocache_headers() 2024-09-17 17:27:37 +02:00
e731831d29 Preserve selected Woo email dummy content type on history undo/redo
[MAILPOET-6213]
2024-09-17 14:04:26 +02:00
71405b9555 Fix reset template functionality to work for multiple reset
The issue was that after the first reset the global template object
became a model and all changes were save also to this object so
subsequent resets didn't work.

This commit fixes it by making sure we clone the original template before resetting.
[MAILPOET-6213]
2024-09-17 14:04:26 +02:00
30520f08fa Fix typo in the method name in DataInconsistencyRepository
[MAILPOET-6213]
2024-09-17 14:04:26 +02:00
79f12dfeb4 Add reset template button and reset template functionality
[MAILPOET-6213]
2024-09-17 14:04:26 +02:00
f46573eb5f Unify property type annotations in Newsletter Editor page controller
[MAILPOET-6213]
2024-09-17 14:04:26 +02:00
844fa02a06 Make the original Woo Transactional email template available to JS app
[MAILPOET-6213]
2024-09-17 14:04:26 +02:00
b962252c03 Update used WooCommerce Subscriptions plugin in Circle CI
- latest version: 6.7.0
 - previous version: 6.6.2
2024-09-17 10:23:06 +02:00
c50f638463 Update used WooCommerce plugin in Circle CI
- latest version: 9.3.1
 - previous version: 9.2.3
2024-09-17 10:23:06 +02:00
ae642b1974 Update used WordPress images in Circle CI
- latest version: 6.6.2-php8.3
 - previous version: 6.5.5
2024-09-17 10:23:06 +02:00
1f92ac551e Use alias that is not a keyword
Together with fixing the MySQL platform detection this is not necessary,
but it's easy to use a safe alias that is not a keyword, in this case.

[MAILPOET-6232]
2024-09-17 09:37:58 +02:00
ce526e84e0 Do not set MySQL platform autoamtically, enable auto-detection
This will enable correct detection of MySQL vs MariaDB platform in Doctrine,
as well as they particular versions, such as 5.7 or 8.4, etc.

[MAILPOET-6232]
2024-09-17 09:37:58 +02:00
4b633ccdf6 Remove unused MailPoet\Utils\ProgressBar
[MAILPOET-6227]
2024-09-16 16:01:43 -06:00
9fb48d39b4 pnpm audit --fix
[MAILPOET-6229]
2024-09-16 12:42:25 +02:00
b6e6e93066 Remove pnpm.overrides from nested package as they are not used
[MAILPOET-6229]
2024-09-16 12:42:25 +02:00
6b77cfde45 Update micromatch
[MAILPOET-6229]
2024-09-16 12:42:25 +02:00
2673a30177 Update express
[MAILPOET-6229]
2024-09-16 12:42:25 +02:00
0a1cf84da3 Update serve-static
[MAILPOET-6229]
2024-09-16 12:42:25 +02:00
876c224708 Update send package
[MAILPOET-6229]
2024-09-16 12:42:25 +02:00
03fdcfb150 Update body-parser
[MAILPOET-6229]
2024-09-16 12:42:25 +02:00
0d9aebdce1 Update path-to-regexp
[MAILPOET-6229]
2024-09-16 12:42:25 +02:00
bccd455e6f Remove unnecessary code replacements for twig
twig_xxx functions were deprecated and are no longer used in twig codebase
2024-09-16 10:21:05 +02:00
b23c3b4704 Bump twig/twig from 3.10.3 to 3.11.1 in /mailpoet/prefixer
Bumps [twig/twig](https://github.com/twigphp/Twig) from 3.10.3 to 3.11.1.
- [Changelog](https://github.com/twigphp/Twig/blob/v3.11.1/CHANGELOG)
- [Commits](https://github.com/twigphp/Twig/compare/v3.10.3...v3.11.1)

---
updated-dependencies:
- dependency-name: twig/twig
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-16 10:21:05 +02:00
f483d40c19 Clean settings cache when reinstalling the plugin 2024-09-13 10:34:55 +02:00
a29233407f Use cached WordPress and WooCommerce segment entities 2024-09-13 10:34:55 +02:00
b512079ce2 Replace settings fetch() calls with cached get() 2024-09-13 10:34:55 +02:00
b32c6aa233 Remove no longer needed populator logic 2024-09-13 10:34:55 +02:00
a416cecddf Optimize populating newsletter option fields 2024-09-13 10:34:55 +02:00
974add271a Optimize populating newsletter templates 2024-09-13 10:34:55 +02:00
5e333fde27 Bump webpack from 5.92.0 to 5.94.0
Bumps [webpack](https://github.com/webpack/webpack) from 5.92.0 to 5.94.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.92.0...v5.94.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-13 10:22:04 +02:00
8a6a4fd29d Add WordPress-VIP-Go ruleset to CodeSniffer 2024-09-12 15:11:08 +02:00
e425304592 Release 5.2.0 2024-09-12 12:42:18 +02:00
1fe42a2afc Improve WP-Cron notice by checking whether the cron is running 2024-09-12 10:06:14 +02:00
5781351e15 Fix deleting orphaned subscriber tasks in batches
[MAILPOET-6219]
2024-09-11 15:19:35 +02:00
9960a56a75 Use temporary tables for orphaned scheduled task subscribers
This will ensure the intermediate results are materialized first.

[MAILPOET-6219]
2024-09-11 15:19:35 +02:00
53a1664133 Optimize queries for orphaned scheduled task subscribers
[MAILPOET-6219]
2024-09-11 15:19:35 +02:00
f3d6813d97 Load data inconsistencies async from API
[MAILPOET-6219]
2024-09-11 15:19:35 +02:00
a4c901fba7 Fix Help > System Status > Last run started displays unknown
[MAILPOET-6222]
2024-09-11 11:04:02 +02:00
db6d1e9546 Fix not opened stats on subscriber stats page
[MAILPOET-6220]
2024-09-11 08:53:48 +02:00
88c53a727e Iterate through nested block in rendering Preprocessor
[MAILPOET-6212]
2024-09-09 15:31:24 +02:00
45f4a69645 Update used WooCommerce Subscriptions plugin in Circle CI
- latest version: 6.6.2
 - previous version: 6.5.0
2024-09-09 11:00:49 +02:00
c50a774e85 Update used Automate Woo plugin in Circle CI
- latest version: 6.1.0
 - previous version: 6.0.33
2024-09-09 11:00:49 +02:00
234718a712 Fix ShellCheck lint SC2068 in lint-staged-php
Unlikely to cause issue, but ShellCheck linter was not happy

https://www.shellcheck.net/wiki/SC2068
2024-09-06 09:25:14 +02:00
d90f0ae533 Fix unresolved command in lint-staged-php for Linux
The 'source' command is not available in the default sh shell on Linux. The source command is specific to bash and other compatible shells. On Linux, the default sh shell is often dash, which does not support source. It seem to work on macOS because the default shell there is bash.

The . (dot) command is POSIX-compliant and works in both sh and bash.
2024-09-06 09:25:14 +02:00
ebe9a3cc2e Fix Doctrine fixer breaks lint-staged for PHP
Pre-commit hooks were failing with PHP fatal error after correcting invalid 'rm' commands in Doctrine fixer in the previous commit.
2024-09-06 09:25:14 +02:00
d8ccfa4e32 Fix invalid 'rm' commands in Doctrine fixer
No space between the command option (-r) and the file path
2024-09-06 09:25:14 +02:00
8e856abada Release 5.1.1 2024-09-05 13:18:43 +02:00
8646238251 Remove ./do qa:mininal-plugin-standard from git hooks
This check has been removed in https://github.com/mailpoet/mailpoet/pull/5801
The functionality is now covered by code sniffer
[MAILPOET-6150]
2024-09-05 12:55:23 +02:00
fed7a48680 Revert "Replace interact.js with interactjs"
This reverts commit 5c349a506b.

[MAILPOET-6211]
2024-09-04 18:53:07 +02:00
bb5e398e8f Revert "Fix calculating drop zone position"
This reverts commit 8c2f41dcf1.

[MAILPOET-6211]
2024-09-04 18:53:07 +02:00
d553e4647d Revert "Fix cloning dragged element"
This reverts commit 08f0f2bf38.

[MAILPOET-6211]
2024-09-04 18:53:07 +02:00
65516e70ed Revert "Prevent text selection when dragging"
This reverts commit e4730f7e31.

[MAILPOET-6211]
2024-09-04 18:53:07 +02:00
e7466fc9df Revert "Prevent text selection when resizing"
This reverts commit c11460fd30.

[MAILPOET-6211]
2024-09-04 18:53:07 +02:00
4882b2aef6 Revert "Fixed dragging images after being resized"
This reverts commit 16525d5cce.

[MAILPOET-6211]
2024-09-04 18:53:07 +02:00
2a4953489e Revert "Fix deprecation warning from interact.js"
This reverts commit 0c000b0595.

[MAILPOET-6211]
2024-09-04 18:53:07 +02:00
9ed2e59a74 Update used WooCommerce Subscriptions plugin in Circle CI
- latest version: 6.6.1
 - previous version: 6.5.0
2024-09-03 16:09:03 +02:00
c4bc285d28 Update used Automate Woo plugin in Circle CI
- latest version: 6.0.33
 - previous version: 5.8.5
2024-09-03 16:09:03 +02:00
1408e7135c Update used WooCommerce plugin in Circle CI
- latest version: 9.2.3
 - previous version: 9.1.4
2024-09-03 16:09:03 +02:00
56c1a34120 Release 5.1.0 2024-09-03 16:01:56 +02:00
f68160fe5b Fix typos in WordPress Playground link action
[MAILPOET-6185]
2024-09-02 21:33:40 +02:00
920 changed files with 44040 additions and 21880 deletions

View File

@ -99,12 +99,12 @@ executors:
wpcli_php_max_wporg:
<<: *default_job_config
docker:
- image: mailpoet/wordpress:8.1_20230307.1
- image: mailpoet/wordpress:8.1_20230307.1 # We need to use 8.1 to emulate the WP.org environment
wpcli_php_latest:
<<: *default_job_config
docker:
- image: mailpoet/wordpress:8.1_20230307.1
- image: mailpoet/wordpress:8.2_20241126.1
wpcli_php_mysql_oldest:
<<: *default_job_config
@ -115,7 +115,7 @@ executors:
wpcli_php_mysql_latest:
<<: *default_job_config
docker:
- image: mailpoet/wordpress:8.1_20230307.1
- image: mailpoet/wordpress:8.2_20241126.1
- image: cimg/mysql:8.0
command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_520_ci
@ -141,6 +141,8 @@ jobs:
key: composer-{{ checksum "tasks/code_sniffer/composer.json" }}-{{ checksum "tasks/code_sniffer/composer.lock" }}
- restore_cache:
key: composer-{{ checksum "composer.json" }}-{{ checksum "composer.lock" }}
- restore_cache:
key: composer-{{ checksum "../tests_env/composer.json" }}-{{ checksum "../tests_env/composer.lock" }}
- restore_cache:
key: composer-prefixed-{{ checksum "prefixer-checksum" }}
- restore_cache:
@ -157,7 +159,7 @@ jobs:
./do install
./do compile:all --env production --skip-tests
./do doctrine:generate-cache
vendor/bin/codecept build
../tests_env/vendor/bin/codecept build
./do twig:generate-cache
- run:
name: 'Check Prettier formatting'
@ -178,6 +180,10 @@ jobs:
key: composer-{{ checksum "composer.json" }}-{{ checksum "composer.lock" }}
paths:
- vendor
- save_cache:
key: composer-{{ checksum "../tests_env/composer.json" }}-{{ checksum "../tests_env/composer.lock" }}
paths:
- ../tests_env/vendor
- save_cache:
key: composer-prefixed-{{ checksum "prefixer-checksum" }}
paths:
@ -191,10 +197,10 @@ jobs:
- run:
name: Download additional WP Plugins for tests
command: |
./do download:woo-commerce-zip 9.2.2
./do download:woo-commerce-subscriptions-zip 6.6.0
./do download:woo-commerce-zip 9.6.1
./do download:woo-commerce-subscriptions-zip 7.1.0
./do download:woo-commerce-memberships-zip 1.26.5
./do download:automate-woo-zip 6.0.32
./do download:automate-woo-zip 6.1.5
- run:
name: Dump tests ENV variables for acceptance tests
command: |
@ -445,19 +451,19 @@ jobs:
- run:
name: 'Pull test docker images'
# Pull docker images with 3 retries
command: i='0';while ! docker-compose -f ../tests_env/docker/docker-compose.yml pull && ((i < 3)); do sleep 3 && i=$[$i+1]; done
command: i='0';while ! docker compose -f ../tests_env/docker/docker-compose.yml pull && ((i < 3)); do sleep 3 && i=$[$i+1]; done
- run:
name: Create docker containers for test
# We experienced some failures when creating containers so we do it explicitly with one retry
command: |
cd ../tests_env/docker
docker-compose create || docker-compose create
docker compose create || docker compose create
- run:
# Some tools we use may need different version based on PHP version used in docker
name: Ensure correct versions of tools
command: |
cd ../tests_env/docker
docker-compose run --rm -w /project -e COMPOSER_DEV_MODE=1 --entrypoint "php tools/install.php" codeception_acceptance
docker compose run --rm -w /project -e COMPOSER_DEV_MODE=1 --entrypoint "php tools/install.php" codeception_acceptance
- when:
condition: ${WOOCOMMERCE_VERSION}
steps:
@ -465,7 +471,7 @@ jobs:
name: Download WooCommerce Core
command: |
cd ../tests_env/docker
docker-compose run --rm -w /project --entrypoint "./do download:woo-commerce-zip ${WOOCOMMERCE_VERSION}" --no-deps -e WP_GITHUB_USERNAME=${WP_GITHUB_USERNAME} -e WP_GITHUB_TOKEN=${WP_GITHUB_TOKEN} codeception_acceptance
docker compose run --rm -w /project --entrypoint "./do download:woo-commerce-zip ${WOOCOMMERCE_VERSION}" --no-deps -e WP_GITHUB_USERNAME=${WP_GITHUB_USERNAME} -e WP_GITHUB_TOKEN=${WP_GITHUB_TOKEN} codeception_acceptance
- when:
condition: << parameters.woo_subscriptions_version >>
steps:
@ -473,7 +479,7 @@ jobs:
name: Download WooCommerce Subscriptions
command: |
cd ../tests_env/docker
docker-compose run --rm -w /project --entrypoint "./do download:woo-commerce-subscriptions-zip << parameters.woo_subscriptions_version >>" --no-deps -e WP_GITHUB_USERNAME=${WP_GITHUB_USERNAME} -e WP_GITHUB_TOKEN=${WP_GITHUB_TOKEN} codeception_acceptance
docker compose run --rm -w /project --entrypoint "./do download:woo-commerce-subscriptions-zip << parameters.woo_subscriptions_version >>" --no-deps -e WP_GITHUB_USERNAME=${WP_GITHUB_USERNAME} -e WP_GITHUB_TOKEN=${WP_GITHUB_TOKEN} codeception_acceptance
- when:
condition: << parameters.woo_memberships_version >>
steps:
@ -481,7 +487,7 @@ jobs:
name: Download WooCommerce Memberships
command: |
cd ../tests_env/docker
docker-compose run --rm -w /project --entrypoint "./do download:woo-commerce-memberships-zip << parameters.woo_memberships_version >>" --no-deps -e WP_GITHUB_USERNAME=${WP_GITHUB_USERNAME} -e WP_GITHUB_TOKEN=${WP_GITHUB_TOKEN} codeception_acceptance
docker compose run --rm -w /project --entrypoint "./do download:woo-commerce-memberships-zip << parameters.woo_memberships_version >>" --no-deps -e WP_GITHUB_USERNAME=${WP_GITHUB_USERNAME} -e WP_GITHUB_TOKEN=${WP_GITHUB_TOKEN} codeception_acceptance
- when:
condition: << parameters.automate_woo_version >>
steps:
@ -489,7 +495,7 @@ jobs:
name: Download AutomateWoo
command: |
cd ../tests_env/docker
docker-compose run --rm -w /project --entrypoint "./do download:automate-woo-zip << parameters.automate_woo_version >>" --no-deps -e WP_GITHUB_USERNAME=${WP_GITHUB_USERNAME} -e WP_GITHUB_TOKEN=${WP_GITHUB_TOKEN} codeception_acceptance
docker compose run --rm -w /project --entrypoint "./do download:automate-woo-zip << parameters.automate_woo_version >>" --no-deps -e WP_GITHUB_USERNAME=${WP_GITHUB_USERNAME} -e WP_GITHUB_TOKEN=${WP_GITHUB_TOKEN} codeception_acceptance
- run:
name: Group acceptance tests
command: |
@ -518,7 +524,7 @@ jobs:
--xml
-g circleci_split_group
)
docker-compose run -e SKIP_DEPS=1 \
docker compose run -e SKIP_DEPS=1 \
-e CIRCLE_BRANCH=${CIRCLE_BRANCH} \
-e CIRCLE_JOB=${CIRCLE_JOB} \
-e MULTISITE=<< parameters.multisite >> \
@ -577,13 +583,13 @@ jobs:
- run:
name: 'Pull test docker images'
# Pull docker images with 3 retries
command: i='0';while ! docker-compose -f tests/performance/docker-compose.yml pull && ((i < 3)); do sleep 3 && i=$[$i+1]; done
command: i='0';while ! docker compose -f tests/performance/docker-compose.yml pull && ((i < 3)); do sleep 3 && i=$[$i+1]; done
- run:
name: Create docker containers for test
# We experienced some failures when creating containers so we do it explicitly with one retry
command: |
cd tests/performance
docker-compose create || docker-compose create
docker compose create || docker compose create
- run:
name: Run performance tests
command: |
@ -741,19 +747,19 @@ jobs:
- run:
name: 'Pull test docker images'
# Pull docker images with 3 retries
command: i='0';while ! docker-compose -f ../tests_env/docker/docker-compose.yml pull && ((i < 3)); do sleep 3 && i=$[$i+1]; done
command: i='0';while ! docker compose -f ../tests_env/docker/docker-compose.yml pull && ((i < 3)); do sleep 3 && i=$[$i+1]; done
- run:
name: Create docker containers for test
# We experienced some failures when creating containers so we do it explicitly with one retry
command: |
cd ../tests_env/docker
docker-compose create || docker-compose create
docker compose create || docker compose create
- run:
# Some tools we use may need different version based on PHP version used in docker
name: Ensure correct versions of tools
command: |
cd ../tests_env/docker
docker-compose run --rm -w /project -e COMPOSER_DEV_MODE=1 --entrypoint "php tools/install.php" codeception_integration
docker compose run --rm -w /project -e COMPOSER_DEV_MODE=1 --entrypoint "php tools/install.php" codeception_integration
- when:
condition: ${WOOCOMMERCE_VERSION}
steps:
@ -761,7 +767,7 @@ jobs:
name: Download WooCommerce Core
command: |
cd ../tests_env/docker
docker-compose run --rm -w /project --entrypoint "./do download:woo-commerce-zip ${WOOCOMMERCE_VERSION}" --no-deps -e WP_GITHUB_USERNAME=${WP_GITHUB_USERNAME} -e WP_GITHUB_TOKEN=${WP_GITHUB_TOKEN} codeception_integration
docker compose run --rm -w /project --entrypoint "./do download:woo-commerce-zip ${WOOCOMMERCE_VERSION}" --no-deps -e WP_GITHUB_USERNAME=${WP_GITHUB_USERNAME} -e WP_GITHUB_TOKEN=${WP_GITHUB_TOKEN} codeception_integration
- when:
condition: << parameters.woo_subscriptions_version >>
steps:
@ -769,7 +775,7 @@ jobs:
name: Download WooCommerce Subscriptions
command: |
cd ../tests_env/docker
docker-compose run --rm -w /project --entrypoint "./do download:woo-commerce-subscriptions-zip << parameters.woo_subscriptions_version >>" --no-deps -e WP_GITHUB_USERNAME=${WP_GITHUB_USERNAME} -e WP_GITHUB_TOKEN=${WP_GITHUB_TOKEN} codeception_integration
docker compose run --rm -w /project --entrypoint "./do download:woo-commerce-subscriptions-zip << parameters.woo_subscriptions_version >>" --no-deps -e WP_GITHUB_USERNAME=${WP_GITHUB_USERNAME} -e WP_GITHUB_TOKEN=${WP_GITHUB_TOKEN} codeception_integration
- when:
condition: << parameters.woo_memberships_version >>
steps:
@ -777,7 +783,7 @@ jobs:
name: Download WooCommerce Memberships
command: |
cd ../tests_env/docker
docker-compose run --rm -w /project --entrypoint "./do download:woo-commerce-memberships-zip << parameters.woo_memberships_version >>" --no-deps -e WP_GITHUB_USERNAME=${WP_GITHUB_USERNAME} -e WP_GITHUB_TOKEN=${WP_GITHUB_TOKEN} codeception_integration
docker compose run --rm -w /project --entrypoint "./do download:woo-commerce-memberships-zip << parameters.woo_memberships_version >>" --no-deps -e WP_GITHUB_USERNAME=${WP_GITHUB_USERNAME} -e WP_GITHUB_TOKEN=${WP_GITHUB_TOKEN} codeception_integration
- when:
condition: << parameters.automate_woo_version >>
steps:
@ -785,7 +791,7 @@ jobs:
name: Download AutomateWoo
command: |
cd ../tests_env/docker
docker-compose run --rm -w /project --entrypoint "./do download:automate-woo-zip << parameters.automate_woo_version >>" --no-deps -e WP_GITHUB_USERNAME=${WP_GITHUB_USERNAME} -e WP_GITHUB_TOKEN=${WP_GITHUB_TOKEN} codeception_integration
docker compose run --rm -w /project --entrypoint "./do download:automate-woo-zip << parameters.automate_woo_version >>" --no-deps -e WP_GITHUB_USERNAME=${WP_GITHUB_USERNAME} -e WP_GITHUB_TOKEN=${WP_GITHUB_TOKEN} codeception_integration
- run:
name: 'PHP Integration tests'
command: |
@ -804,7 +810,7 @@ jobs:
if [[ -n '<< parameters.skip_group >>' ]]; then
args+=(--skip-group << parameters.skip_group >>)
fi
docker-compose run -e SKIP_DEPS=1 \
docker compose run -e SKIP_DEPS=1 \
-e CIRCLE_BRANCH=${CIRCLE_BRANCH} \
-e CIRCLE_JOB=${CIRCLE_JOB} \
-e SKIP_PLUGINS=<< parameters.skip_plugins >> \
@ -934,40 +940,28 @@ workflows:
name: acceptance_tests_base_and_woo
enable_hpos: 1
requires:
- unit_tests
- static_analysis_php8
- qa_js
- qa_php
- build
- acceptance_tests:
<<: *slack-fail-post-step
name: acceptance_tests_woo_hpos_sync_on
group: woo
enable_hpos_sync: 1
requires:
- unit_tests
- static_analysis_php8
- qa_js
- qa_php
- build
- acceptance_tests:
<<: *slack-fail-post-step
name: acceptance_tests_woo_hpos_off
group: woo
disable_hpos: 1
requires:
- unit_tests
- static_analysis_php8
- qa_js
- qa_php
- build
- acceptance_tests:
<<: *slack-fail-post-step
name: acceptance_tests_blockbased_theme
group: frontend
blockbased_theme: 1
requires:
- unit_tests
- static_analysis_php8
- qa_js
- qa_php
- build
- js_tests:
<<: *slack-fail-post-step
requires:
@ -978,55 +972,41 @@ workflows:
enable_hpos_sync: 1
name: integration_test_woo_hpos_sync_on
requires:
- unit_tests
- static_analysis_php8
- qa_js
- qa_php
- build
- integration_tests:
<<: *slack-fail-post-step
group: woo
name: integration_test_woo_hpos_on
enable_hpos: 1
requires:
- unit_tests
- static_analysis_php8
- qa_js
- qa_php
- build
- integration_tests:
<<: *slack-fail-post-step
group: woo
disable_hpos: 1
name: integration_test_woo_hpos_off
requires:
- unit_tests
- static_analysis_php8
- qa_js
- qa_php
- build
- integration_tests:
<<: *slack-fail-post-step
skip_group: woo
skip_plugins: 1
name: integration_test_base
requires:
- unit_tests
- static_analysis_php8
- qa_js
- qa_php
- build
- acceptance_tests:
<<: *slack-fail-post-step
<<: *multisite_acceptance_config
name: acceptance_tests_multisite
requires:
- build
- integration_tests:
<<: *slack-fail-post-step
<<: *only_trunk_and_release
multisite: 1
name: integration_tests_multisite
requires:
- unit_tests
- static_analysis_php7
- static_analysis_php8
- qa_js
- qa_php
- build
- acceptance_tests:
<<: *slack-fail-post-step
<<: *only_release
@ -1055,9 +1035,18 @@ workflows:
- integration_test_woo_hpos_on
- integration_test_woo_hpos_off
- integration_test_woo_hpos_sync_on
- integration_with_premium_latest
- acceptance_tests_woo_hpos_sync_on
- acceptance_tests_woo_hpos_off
- acceptance_tests_blockbased_theme
- static_analysis_php8
- static_analysis_php7
- unit_tests
- qa_js
- qa_php
- qa_php_oldest
- security_analysis
- qa_php_max_wporg
- qit_security_scan:
<<: *slack-fail-post-step
requires:
@ -1093,15 +1082,15 @@ workflows:
- acceptance_tests:
<<: *slack-fail-post-step
name: acceptance_oldest
woo_core_version: 9.1.4
woo_subscriptions_version: 6.5.0
woo_core_version: 9.5.2
woo_subscriptions_version: 7.0.0
woo_memberships_version: 1.25.2
automate_woo_version: 5.8.5
automate_woo_version: 6.0.33
mysql_command: --max_allowed_packet=100M
mysql_image: mysql:5.5
codeception_image_version: 7.4-cli_20220605.0
wordpress_image_version: 6.1.1-php7.4 # We use image with PHP 7.4 and install required WordPress version via CLI
wordpress_version: 6.5.5
wordpress_version: 6.6.2
requires:
- build
- performance_tests:
@ -1134,13 +1123,13 @@ workflows:
- integration_tests:
<<: *slack-fail-post-step
name: integration_oldest
woo_core_version: 9.1.4
woo_subscriptions_version: 6.5.0
woo_core_version: 9.5.2
woo_subscriptions_version: 7.0.0
woo_memberships_version: 1.25.2
automate_woo_version: 5.8.5
automate_woo_version: 6.0.33
codeception_image_version: 7.4-cli_20220605.0
wordpress_image_version: 6.1.1-php7.4 # We use image with PHP 7.4 and install required WordPress version via CLI # We use image with PHP 7.4 and install required WordPress version via CLI
wordpress_version: 6.5.5
wordpress_version: 6.6.2
mysql_command: --max_allowed_packet=100M
mysql_image: mysql:5.5
requires:
@ -1197,25 +1186,25 @@ workflows:
- acceptance_tests:
<<: *slack-fail-post-step
name: acceptance_with_premium_oldest
woo_core_version: 9.1.4
woo_subscriptions_version: 6.5.0
woo_core_version: 9.5.2
woo_subscriptions_version: 7.0.0
woo_memberships_version: 1.25.2
automate_woo_version: 5.8.5
automate_woo_version: 6.0.33
codeception_image_version: 7.4-cli_20220605.0
wordpress_image_version: 6.1.1-php7.4 # We use image with PHP 7.4 and install required WordPress version via CLI
wordpress_version: 6.5.5
wordpress_version: 6.6.2
requires:
- build_premium
- integration_tests:
<<: *slack-fail-post-step
name: integration_with_premium_oldest
woo_core_version: 9.1.4
woo_subscriptions_version: 6.5.0
woo_core_version: 9.5.2
woo_subscriptions_version: 7.0.0
woo_memberships_version: 1.25.2
automate_woo_version: 5.8.5
automate_woo_version: 6.0.33
codeception_image_version: 7.4-cli_20220605.0
wordpress_image_version: 6.1.1-php7.4 # We use image with PHP 7.4 and install required WordPress version via CLI
wordpress_version: 6.5.5
wordpress_version: 6.6.2
mysql_command: --max_allowed_packet=100M
mysql_image: mysql:5.5
requires:

View File

@ -10,6 +10,12 @@ indent_size = 2
ij_smart_tabs = false
max_line_length = off
[packages/php/email-editor/**]
indent_style = tab
[packages/js/email-editor/**.{js,jsx,ts,tsx,scss}]
indent_style = tab
[*.php]
ij_php_align_key_value_pairs = false
ij_php_align_multiline_chained_methods = false
@ -55,3 +61,5 @@ ij_php_space_after_for_semicolon = true
ij_php_space_after_colon_in_return_type = true
ij_php_space_before_else_keyword = true
ij_php_for_statement_new_line_after_left_paren = true
ij_php_class_brace_style = end_of_line
ij_php_comma_after_last_array_element = true

View File

@ -39,3 +39,15 @@ e66c76133ec3ef667e382203426d91a4b4aa5174
# Prettier autoformatting
ab27eaee2df740c0add4331a7f8c115a87ecfa2b
# Move email editor to JS packages folder
912282f57ccc839491ff951ec5cf7aa10c14f429
# Switch email editor js packages to WP coding style
b2fb96f8793b63db629d5237010d87332330c51e
# Email editor Prettier autoformatting
8c604453b1d82e3a2c731241e1c96ea8b32ec716
# Move email editor components out of the engine folder
1c3ea9cd0a5fc8848a64d840e2fa16a6c7d8c1fe

View File

@ -0,0 +1,212 @@
name: Email Editor Package Tests
on:
push:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
php-version: ['7.4', '8.2']
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Cache Composer vendor dependencies for MailPoet
id: composer-mailpoet-cache
uses: actions/cache@v4
with:
path: mailpoet/vendor
key: ${{ runner.os }}-composer-mailpoet-${{ matrix.php-version }}-${{ hashFiles('mailpoet/composer.lock') }}-${{ hashFiles('mailpoet/composer.json') }}
- name: Cache Composer vendor-prefixed dependencies for MailPoet
id: vendor-prefixed-cache
uses: actions/cache@v4
with:
path: mailpoet/vendor-prefixed
key: ${{ runner.os }}-vendor-prefixed-${{ matrix.php-version }}-${{ hashFiles('mailpoet/prefixer/composer.lock') }}-${{ hashFiles('mailpoet/prefixer/composer.json') }}
- name: Cache Composer vendor for test environment
id: composer-tests-env-cache
uses: actions/cache@v4
with:
path: tests_env/vendor
key: ${{ runner.os }}-composer-mailpoet-${{ matrix.php-version }}-${{ hashFiles('tests_env/composer.lock') }}-${{ hashFiles('tests_env/composer.json') }}
- name: Cache Composer dependencies for Email Editor
id: composer-email-editor-cache
uses: actions/cache@v4
with:
path: packages/php/email-editor/vendor
key: ${{ runner.os }}-composer-email-editor-${{ matrix.php-version }}-${{ hashFiles('packages/php/email-editor/composer.lock') }}-${{ hashFiles('packages/php/email-editor/composer.json') }}
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
extensions: gd
- name: Install tools
run: |
COMPOSER_DEV_MODE=1 php tools/install.php
touch .env
working-directory: mailpoet
# Install Test Environment dependencies only if the cache was not hit
- name: Install test environment dependencies
if: steps.composer-tests-env-cache.outputs.cache-hit != 'true'
run: ../mailpoet/tools/vendor/composer.phar install
working-directory: tests_env
# Install MailPoet dependencies only if the cache was not hit
- name: Install mailpoet dependencies
if: |
steps.composer-mailpoet-cache.outputs.cache-hit != 'true' || steps.vendor-prefixed-cache.outputs.cache-hit != 'true'
run: ./tools/vendor/composer.phar install
working-directory: mailpoet
# Install Email Editor dependencies only if the cache was not hit
- name: Install email-editor dependencies
if: steps.composer-email-editor-cache.outputs.cache-hit != 'true'
run: ../../../mailpoet/tools/vendor/composer.phar install
working-directory: packages/php/email-editor
# Dump Email Editor autoload
# This is needed to refresh classmap autoload when the composer cache is hit
- name: Dump email-editor autoload
run: ../../../mailpoet/tools/vendor/composer.phar dump-autoload
working-directory: packages/php/email-editor
# Dump MailPoet autoload
# This is needed to refresh classmap autoload when the composer cache is hit
- name: Dump MailPoet autoload
run: ./tools/vendor/composer.phar dump-autoload
working-directory: mailpoet
# Run Email Editor unit tests
- name: Run email-editor package unit tests
run: ../../../tests_env/vendor/bin/codecept build && ../../../mailpoet/tools/vendor/composer.phar unit-test
working-directory: packages/php/email-editor
- name: Run email-editor package integration tests
run: ../../../mailpoet/tools/vendor/composer.phar integration-test
working-directory: packages/php/email-editor
code-style:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
- name: Install tools
run: |
COMPOSER_DEV_MODE=1 php tools/install.php
touch .env
working-directory: mailpoet
- name: Install composer dependencies
run: ../../tools/vendor/composer.phar install
working-directory: mailpoet/tasks/code_sniffer
- name: Run code style check
run: ../../../mailpoet/tools/vendor/composer.phar code-style
working-directory: packages/php/email-editor
phpstan-static-analysis:
runs-on: ubuntu-latest
strategy:
matrix:
php-version: ['7.4', '8.2']
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Cache Composer vendor dependencies for MailPoet
id: composer-mailpoet-cache
uses: actions/cache@v4
with:
path: mailpoet/vendor
key: ${{ runner.os }}-composer-mailpoet-${{ matrix.php-version }}-${{ hashFiles('mailpoet/composer.lock') }}-${{ hashFiles('mailpoet/composer.json') }}
- name: Cache Composer vendor-prefixed dependencies for MailPoet
id: vendor-prefixed-cache
uses: actions/cache@v4
with:
path: mailpoet/vendor-prefixed
key: ${{ runner.os }}-vendor-prefixed-${{ matrix.php-version }}-${{ hashFiles('mailpoet/prefixer/composer.lock') }}-${{ hashFiles('mailpoet/prefixer/composer.json') }}
- name: Cache Composer vendor for test environment
id: composer-tests-env-cache
uses: actions/cache@v4
with:
path: tests_env/vendor
key: ${{ runner.os }}-composer-mailpoet-${{ matrix.php-version }}-${{ hashFiles('tests_env/composer.lock') }}-${{ hashFiles('tests_env/composer.json') }}
- name: Cache Composer dependencies for Email Editor
id: composer-email-editor-cache
uses: actions/cache@v4
with:
path: packages/php/email-editor/vendor
key: ${{ runner.os }}-composer-email-editor-${{ matrix.php-version }}-${{ hashFiles('packages/php/email-editor/composer.lock') }}-${{ hashFiles('packages/php/email-editor/composer.json') }}
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
extensions: gd
- name: Install tools
run: |
COMPOSER_DEV_MODE=1 php tools/install.php
touch .env
working-directory: mailpoet
# Install Test Environment dependencies only if the cache was not hit
- name: Install test environment dependencies
if: steps.composer-tests-env-cache.outputs.cache-hit != 'true'
run: ../mailpoet/tools/vendor/composer.phar install
working-directory: tests_env
# Install MailPoet dependencies only if the cache was not hit
- name: Install mailpoet dependencies
if: |
steps.composer-mailpoet-cache.outputs.cache-hit != 'true' || steps.vendor-prefixed-cache.outputs.cache-hit != 'true'
run: ./tools/vendor/composer.phar install
working-directory: mailpoet
# Install Email Editor dependencies only if the cache was not hit
- name: Install email-editor dependencies
if: steps.composer-email-editor-cache.outputs.cache-hit != 'true'
run: ../../../mailpoet/tools/vendor/composer.phar install
working-directory: packages/php/email-editor
- name: Install composer dependencies
run: ../../tools/vendor/composer.phar install
working-directory: mailpoet/tasks/phpstan
# Dump Email Editor autoload
# This is needed to refresh classmap autoload when the composer cache is hit
- name: Dump email-editor autoload
run: ../../../mailpoet/tools/vendor/composer.phar dump-autoload
working-directory: packages/php/email-editor
# Dump MailPoet autoload
# This is needed to refresh classmap autoload when the composer cache is hit
- name: Dump MailPoet autoload
run: ./tools/vendor/composer.phar dump-autoload
working-directory: mailpoet
- name: Run code phpstan
run: ../../../mailpoet/tools/vendor/composer.phar phpstan -- --php-version=${{ matrix.php-version == '7.4' && '70400' || '80200' }}
working-directory: packages/php/email-editor

View File

@ -5,7 +5,7 @@ on:
types: [opened, reopened, synchronize]
jobs:
append-description:
add-wp-playground-link:
runs-on: ubuntu-latest
steps:
- name: Checkout code
@ -20,8 +20,8 @@ jobs:
BRANCH_NAME="${{ github.head_ref }}"
DESCRIPTION="$(gh pr view $PR_NUMBER --json body -q .body)"
HEADING="## Preview"
CONTENT="$(printf "\n\n${HEADING}\n\n[Preview in WordPress Playground](https://account.mailpoet.com/playground/new/branch:${BRANCH_NAME})\n\n_The latest successful build from \`${BRANCH_NAME}\` will be used. If none is available, the link won't work._")"
CONTENT="$(printf "${HEADING}\n\n[Preview in WordPress Playground](https://account.mailpoet.com/playground/new/branch:${BRANCH_NAME})\n\n_The latest successful build from \`${BRANCH_NAME}\` will be used. If none is available, the link won't work._")"
if [[ "$DESCRIPTION" != *"$HEADING"* ]]; then
gh pr edit $PR_NUMBER --body "${DESCRIPTION}\n\n${CONTENT}"
gh pr edit $PR_NUMBER --body "$(printf "${DESCRIPTION}\n\n${CONTENT}")"
fi

2
.gitignore vendored
View File

@ -9,3 +9,5 @@ npm-debug.log
mailpoet-premium
tsconfig.tsbuildinfo
/wordpress
packages/php/*/vendor
tests_env/vendor

View File

@ -7,7 +7,6 @@ export MP_GIT_HOOKS_ESLINT="${MP_GIT_HOOKS_ESLINT:-true}"
export MP_GIT_HOOKS_STYLELINT="${MP_GIT_HOOKS_STYLELINT:-true}"
export MP_GIT_HOOKS_PHPLINT="${MP_GIT_HOOKS_PHPLINT:-true}"
export MP_GIT_HOOKS_CODE_SNIFFER="${MP_GIT_HOOKS_CODE_SNIFFER:-true}"
export MP_GIT_HOOKS_MINIMAL_PLUGIN_STANDARDS="${MP_GIT_HOOKS_MINIMAL_PLUGIN_STANDARDS:-true}"
export MP_GIT_HOOKS_PHPSTAN="${MP_GIT_HOOKS_PHPSTAN:-true}"
export MP_GIT_HOOKS_INSTALL_JS="${MP_GIT_HOOKS_INSTALL_JS:-false}"
export MP_GIT_HOOKS_INSTALL_PHP="${MP_GIT_HOOKS_INSTALL_PHP:-false}"

View File

@ -4,3 +4,5 @@
[ "$MP_GIT_HOOKS_ENABLE" != "true" ] && exit 0
installIfUpdates
./do cleanup:cached-files

View File

@ -1,7 +1,8 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
. "$(dirname "$0")/common.sh"
[ "$MP_GIT_HOOKS_ENABLE" != "true" ] && exit 0
npx lint-staged -c mailpoet/package.json --cwd mailpoet
npx lint-staged -c package.json
npx lint-staged -c packages/js/email-editor/package.json --cwd packages/js/email-editor
npx lint-staged -c packages/php/email-editor/.lintstagedrc.json --cwd packages/php/email-editor

View File

@ -25,3 +25,5 @@ vendor-prefixed
/mailpoet/views
/mailpoet-premium
/wordpress
/packages/php/email-editor
/packages/js/email-editor

30
.woodpecker.yml Normal file
View File

@ -0,0 +1,30 @@
clone:
git:
image: woodpeckerci/plugin-git
settings:
depth: 1
steps:
build:
image: node:current-bookworm-slim
commands:
- apt update
- apt install php php-symfony bash -y
- npm install pnpm
- cd mailpoet
- bash build.sh
- mkdir ../output
- mv mailpoet.zip ../output
- cd ..
release:
image: woodpeckerci/plugin-gitea-release:latest
settings:
base_url: https://git.cavemanon.xyz
api_key:
from_secret: releasesmithapikey
files: "output/"
prerelease: false
title: "${CI_COMMIT_TAG}"
when:
- event: tag

View File

@ -103,8 +103,8 @@ Then create a Docker Compose override file with NFS settings and restart contain
```shell
cp docker-compose.override.macos-sample.yml docker-compose.override.yml
docker-compose down -v --remove-orphans
docker-compose up -d
docker compose down -v --remove-orphans
docker compose up -d
```
**NOTE:** If you are on MacOS Catalina or newer, make sure to put the repository
@ -163,10 +163,10 @@ To switch the environment to a different PHP version:
dockerfile: dev/{PHP_VERSION}/Dockerfile
```
3. Run `docker-compose build wordpress`.
3. Run `docker compose build wordpress`.
4. Start the stack with `./do start`.
To switch back to the default PHP version remove what was added in 2) and, run `docker-compose build wordpress` for application container and `docker-compose build test_wordpress` for tests container,
To switch back to the default PHP version remove what was added in 2) and, run `docker compose build wordpress` for application container and `docker compose build test_wordpress` for tests container,
and start the stack using `./do start`.
### Disabling the Tracy panel

View File

@ -21,7 +21,7 @@ mkdir -p wordpress/wp-content/plugins/mailpoet-premium
mkdir -p dev/data/mailhog
for plugin in "mailpoet" "mailpoet-premium"; do
docker-compose run --rm wordpress /bin/sh -c "
docker compose run --rm wordpress /bin/sh -c "
[ -d /var/www/html/wp-content/plugins/$plugin ] &&
cd /var/www/html/wp-content/plugins/$plugin &&
./do install &&
@ -29,7 +29,7 @@ for plugin in "mailpoet" "mailpoet-premium"; do
"
done
docker-compose run --rm wordpress /bin/sh -c "
docker compose run --rm wordpress /bin/sh -c "
cd /var/www/templates &&
mkdir assets classes exported
"

View File

@ -29,6 +29,6 @@ cat <<EOT
NFS volume sharing is set up. Recreate your containers and volumes using:
cp docker-compose.override.macos-sample.yml docker-compose.override.yml
docker-compose down -v --remove-orphans
docker-compose up -d
docker compose down -v --remove-orphans
docker compose up -d
EOT

16
do
View File

@ -3,8 +3,8 @@
function syntax {
cat << EOF
./do setup Setup the dev environment.
./do start Start the docker containers (docker-compose up -d).
./do stop Stop the docker containers (docker-compose stop).
./do start Start the docker containers (docker compose up -d).
./do stop Stop the docker containers (docker compose stop).
./do ssh [--test] Run an interactive bash shell inside the plugin directory.
./do run [--test] <command> Run a custom bash command in the wordpress container.
./do acceptance [--premium] Run acceptance tests.
@ -21,7 +21,7 @@ EOF
function ssh_and_run {
params=("$@")
params=("${params[@]:1}")
docker-compose exec $1 bash -c "${params[@]}"
docker compose exec $1 bash -c "${params[@]}"
}
if [ "$1" = "" -o "$1" = "--help" ]; then
@ -31,10 +31,10 @@ elif [ "$1" = "setup" ]; then
./dev/initial-setup.sh
elif [ "$1" = "start" ]; then
docker-compose up -d
docker compose up -d
elif [ "$1" = "stop" ]; then
docker-compose stop
docker compose stop
elif [ "$1" = "run" ]; then
params=("$@")
@ -54,9 +54,9 @@ elif [ "$1" = "ssh" ]; then
fi
if [ "$2" = "--test" ] || [ "$3" = "--test" ]; then
docker-compose exec --workdir $dir test_wordpress bash
docker compose exec --workdir $dir test_wordpress bash
else
docker-compose exec --workdir $dir wordpress bash
docker compose exec --workdir $dir wordpress bash
fi
elif [ "$1" = "acceptance" ]; then
@ -65,7 +65,7 @@ elif [ "$1" = "acceptance" ]; then
else
cd mailpoet
fi
COMPOSE_HTTP_TIMEOUT=200 docker-compose run codeception_acceptance -e KEEP_DEPS=1 --steps --debug -vvv
COMPOSE_HTTP_TIMEOUT=200 docker compose run codeception_acceptance -e KEEP_DEPS=1 --steps --debug -vvv
cd ..
elif [ "$1" = "build" ]; then

View File

@ -1,5 +1,3 @@
version: '3.8'
services:
# for M1 Macs
db:

View File

@ -25,7 +25,7 @@ services:
container_name: mp-wp
build:
context: .
dockerfile: dev/php81/Dockerfile
dockerfile: dev/php82/Dockerfile
args:
UID: ${UID:-1000}
GID: ${GID:-1000}
@ -54,6 +54,7 @@ services:
- './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'
- './tests_env:/var/www/html/wp-content/plugins/tests_env'
- './mailpoet:/var/www/html/wp-content/plugins/mailpoet'
- './mailpoet-premium:/var/www/html/wp-content/plugins/mailpoet-premium'
- './packages:/var/www/html/wp-content/plugins/packages'

View File

@ -51,7 +51,6 @@ MP_GIT_HOOKS_ESLINT=true
MP_GIT_HOOKS_STYLELINT=true
MP_GIT_HOOKS_PHPLINT=true
MP_GIT_HOOKS_CODE_SNIFFER=true
MP_GIT_HOOKS_MINIMAL_PLUGIN_STANDARDS=true
MP_GIT_HOOKS_PHPSTAN=true
MP_GIT_HOOKS_INSTALL_JS=false
MP_GIT_HOOKS_INSTALL_PHP=false

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,7 @@ class RoboFile extends \Robo\Tasks {
return $this->taskExecStack()
->stopOnFail()
->exec('./tools/vendor/composer.phar install')
->exec('cd ../packages/php/email-editor && ../../../mailpoet/tools/vendor/composer.phar install && cd -')
->exec('cd .. && pnpm install --frozen-lockfile --prefer-offline')
->addCode([$this, 'cleanupCachedFiles'])
->run();
@ -32,6 +33,7 @@ class RoboFile extends \Robo\Tasks {
return $this->taskExecStack()
->stopOnFail()
->exec('./tools/vendor/composer.phar install')
->exec('cd ../packages/php/email-editor && ../../../mailpoet/tools/vendor/composer.phar install && cd -')
->addCode([$this, 'cleanupCachedFiles'])
->run();
}
@ -208,7 +210,7 @@ class RoboFile extends \Robo\Tasks {
$env = ($opts['env']) ?
sprintf('./node_modules/.bin/cross-env NODE_ENV="%s"', $opts['env']) :
null;
return $this->_exec($env . ' ./node_modules/webpack/bin/webpack.js --env BUILD_TESTS=' . ($opts['skip-tests'] ? 'skip' : 'build') . '--env BUILD_ONLY_TESTS=' . ($opts['only-tests'] ? 'true' : 'false'));
return $this->_exec($env . ' ./node_modules/webpack/bin/webpack.js --env BUILD_TESTS=' . ($opts['skip-tests'] ? 'skip' : 'build') . ' --env BUILD_ONLY_TESTS=' . ($opts['only-tests'] ? 'true' : 'false'));
}
public function compileCss($opts = ['env' => null]) {
@ -220,7 +222,7 @@ class RoboFile extends \Robo\Tasks {
$compilationResult = $this->taskExecStack()
->exec('pnpm run stylelint-check -- "assets/css/src/**/*.scss"')
->exec('pnpm run scss')
->exec('pnpm run scss' . ($opts['env'] === 'production' ? ' --no-source-map' : ''))
->exec('pnpm run autoprefixer')
->run();
@ -330,7 +332,7 @@ class RoboFile extends \Robo\Tasks {
}
public function testUnit(array $opts = ['file' => null, 'xml' => false, 'multisite' => false, 'debug' => false]) {
$command = 'vendor/bin/codecept run unit';
$command = '../tests_env/vendor/bin/codecept run unit';
if ($opts['file']) {
$command .= ' -f ' . $opts['file'];
@ -404,7 +406,7 @@ class RoboFile extends \Robo\Tasks {
return $this->testIntegration($opts);
}
public function testAcceptance($opts = ['file' => null, 'skip-deps' => false, 'group' => null, 'timeout' => null, 'disable-hpos' => false, 'enable-hpos-sync' => false, 'enable-hpos' => false, 'wordpress-version' => null]) {
public function testAcceptance($opts = ['file' => null, 'skip-deps' => false, 'group' => null, 'timeout' => null, 'disable-hpos' => false, 'enable-hpos-sync' => false, 'enable-hpos' => false, 'wordpress-version' => null, 'skip-plugins' => false]) {
return $this->runTestsInContainer($opts);
}
@ -420,7 +422,7 @@ class RoboFile extends \Robo\Tasks {
->option('env', 'US=' . $opts['us'])
->option('env', 'PW=' . $opts['pw'])
->option('env', 'K6_BROWSER_HEADLESS=' . ($opts['head'] ? 'false' : 'true'))
->option('env', 'K6_BROWSER_TIMEOUT=120s')
->option('env', 'K6_BROWSER_TIMEOUT=' . getenv('K6_BROWSER_TIMEOUT'))
->option('env', 'SCENARIO=' . $opts['scenario'])
->arg($path ?? "$dir/tests/performance/scenarios.js")
->dir($dir)->run();
@ -437,6 +439,7 @@ class RoboFile extends \Robo\Tasks {
->option('env', 'SCENARIO=' . $opts['scenario'])
->option('env', 'K6_CLOUD_TOKEN=' . getenv('K6_CLOUD_TOKEN'))
->option('env', 'K6_CLOUD_ID=' . getenv('K6_CLOUD_ID'))
->option('env', 'K6_BROWSER_TIMEOUT=' . getenv('K6_BROWSER_TIMEOUT'))
->option('env', 'K6_PROJECT_NAME=' . $opts['scenario'])
->option('out', 'cloud')
->arg($path ?? "$dir/tests/performance/scenarios.js")
@ -473,14 +476,14 @@ class RoboFile extends \Robo\Tasks {
// import data & run WordPress setup
$this->say('Importing data and running a WordPress setup...');
$this->taskExec('COMPOSE_HTTP_TIMEOUT=200 docker-compose run --rm -it setup')
$this->taskExec('COMPOSE_HTTP_TIMEOUT=200 docker compose run --rm -it setup')
->dir(__DIR__ . '/tests/performance')
->run();
$this->say('Data imported, WordPress set up.');
}
public function testPerformanceClean() {
$this->taskExec('COMPOSE_HTTP_TIMEOUT=200 docker-compose down --remove-orphans -v')
$this->taskExec('COMPOSE_HTTP_TIMEOUT=200 docker compose down --remove-orphans -v')
->dir(__DIR__ . '/tests/performance')
->run();
}
@ -494,7 +497,7 @@ class RoboFile extends \Robo\Tasks {
*/
public function deleteDocker() {
return $this->taskExec(
'docker-compose down -v --remove-orphans --rmi all'
'docker compose down -v --remove-orphans --rmi all'
)->dir(__DIR__ . '/../tests_env/docker')->run();
}
@ -504,20 +507,20 @@ class RoboFile extends \Robo\Tasks {
public function resetTestDocker() {
return $this
->taskExec(
'docker-compose down -v --remove-orphans'
'docker compose down -v --remove-orphans'
)->dir(__DIR__ . '/../tests_env/docker')
->addCode([$this, 'cleanupCachedFiles'])
->run();
}
public function testFailedUnit() {
$this->_exec('vendor/bin/codecept build');
return $this->_exec('vendor/bin/codecept run unit -g failed');
$this->_exec('../tests_env/vendor/bin/codecept build');
return $this->_exec('../tests_env/vendor/bin/codecept run unit -g failed');
}
public function testFailedIntegration() {
$this->_exec('vendor/bin/codecept build');
return $this->_exec('vendor/bin/codecept run integration -g failed');
$this->_exec('../tests_env/vendor/bin/codecept build');
return $this->_exec('../tests_env/vendor/bin/codecept run integration -g failed');
}
public function containerDump() {
@ -683,11 +686,21 @@ class RoboFile extends \Robo\Tasks {
}
public function qaLintJavascript() {
return $this->_exec('pnpm run check-types && pnpm run lint');
$collection = $this->collectionBuilder();
return $collection->taskExecStack()
->stopOnFail()
->exec('pnpm run check-types && pnpm run lint')
->exec('cd .. && cd packages/js/email-editor && pnpm run check-types && pnpm run lint:js')
->run();
}
public function qaLintCss() {
return $this->_exec('pnpm run stylelint-check -- "assets/css/src/**/*.scss"');
$collection = $this->collectionBuilder();
return $collection->taskExecStack()
->stopOnFail()
->exec('pnpm run stylelint-check -- "assets/css/src/**/*.scss"')
->exec('cd .. && cd packages/js/email-editor && pnpm run lint:css')
->run();
}
public function qaCodeSniffer(array $filesToCheck, $opts = ['severity' => 'all']) {
@ -748,7 +761,7 @@ class RoboFile extends \Robo\Tasks {
return $this->collectionBuilder()
->taskExec(
'./tasks/code_sniffer/vendor/bin/phpcbf ' .
'--standard=./tasks/code_sniffer/MailPoet ' .
'--standard=tasks/code_sniffer/MailPoet/free-ruleset.xml ' .
'--runtime-set testVersion 7.4-8.2 ' .
$filePath . ' -n'
)
@ -774,7 +787,7 @@ class RoboFile extends \Robo\Tasks {
}
// make sure Codeception support files are present to avoid invalid errors when running PHPStan
$this->_exec('vendor/bin/codecept build');
$this->_exec('../tests_env/vendor/bin/codecept build');
// PHPStan must be run out of main plugin directory to avoid its autoloading
// from vendor/autoload.php where some dev dependencies cause conflicts.
@ -1598,7 +1611,7 @@ class RoboFile extends \Robo\Tasks {
}
$annotationReaderProvider = new \MailPoet\Doctrine\Annotations\AnnotationReaderProvider();
$configuration = (new \MailPoet\Doctrine\ConfigurationFactory($annotationReaderProvider, true))->createConfiguration();
$platformClass = \MailPoet\Doctrine\ConnectionFactory::PLATFORM_CLASS;
$platformClass = \MailPoetVendor\Doctrine\DBAL\Platforms\MySQLPlatform::class;
return \MailPoetVendor\Doctrine\ORM\EntityManager::create([
'driverClass' => \MailPoet\Doctrine\ConnectionFactory::DRIVER_CLASS,
'platform' => new $platformClass,
@ -1609,7 +1622,7 @@ class RoboFile extends \Robo\Tasks {
$testType = $opts['test_type'] ?? 'acceptance';
$this->doctrineGenerateCache();
return $this->taskExec(
'COMPOSE_HTTP_TIMEOUT=200 docker-compose run ' .
'COMPOSE_HTTP_TIMEOUT=200 docker compose run ' .
(isset($opts['wordpress-version']) && $opts['wordpress-version'] ? '-e WORDPRESS_VERSION=' . $opts['wordpress-version'] . ' ' : '') .
(isset($opts['skip-deps']) && $opts['skip-deps'] ? '-e SKIP_DEPS=1 ' : '') .
(isset($opts['disable-hpos']) && $opts['disable-hpos'] ? '-e DISABLE_HPOS=1 ' : '') .

View File

@ -1,11 +1,16 @@
.mailpoet_history_wrapper {
display: flex;
display: grid;
grid-gap: $grid-gap;
grid-template-columns: 26px 26px auto;
padding: 12px 20px;
.mailpoet_reset_template {
justify-self: end;
}
}
.mailpoet_history_arrow {
cursor: pointer;
margin-right: 20px;
svg {
display: inline-block;

View File

@ -1,61 +0,0 @@
.mailpoet_feature_announcement {
float: right;
}
.button.mailpoet_feature_announcement_button {
height: 28px;
min-height: auto;
padding: 0 5px 1px;
position: relative;
@include respond-to(small-screen) {
margin-top: 10px;
}
}
.mailpoet_feature_announcement_icon {
line-height: 28px;
}
.mailpoet_feature_announcement_dot:before {
background: #d54e21;
border-radius: 10px;
content: '';
display: block;
height: 10px;
position: absolute;
right: -4px;
top: -4px;
width: 10px;
}
.mailpoet_in_beamer_update_notice {
background: #f00;
bottom: 0;
box-sizing: border-box;
color: #fff;
font-size: 20px;
margin: 0;
padding: 20px 10px;
position: fixed;
right: -400px;
text-align: center;
transition: right 0.2s ease-in;
width: 400px;
z-index: 10000000000; // really has to be this high
a {
color: #fff;
text-decoration: underline;
&:hover,
&:focus {
color: #fff;
text-decoration: none;
}
}
.beamer_show & {
right: 0;
}
}

View File

@ -95,10 +95,6 @@ h1.title.mailpoet-newsletter-listing-heading {
#mailpoet_editor_steps_heading {
.mailpoet-top-bar {
left: 0;
.mailpoet-top-bar-beamer {
top: 4px;
}
}
}

View File

@ -30,6 +30,11 @@
}
}
.mailpoet-template-preview-image {
max-width: 100%;
width: 700px;
}
.mailpoet-template-info {
align-items: center;
display: flex;

View File

@ -90,12 +90,17 @@
width: max-content;
}
.mailpoet-re-engagement-scheduling-note {
color: $color-input-error;
.mailpoet-re-engagement-scheduling {
display: grid;
grid-template-columns: 5fr 2fr 3fr;
.mailpoet-form-input {
width: auto;
}
}
.mailpoet-re-engagement-scheduling .mailpoet-form-input-small {
width: 150px;
.mailpoet-re-engagement-scheduling-note {
color: $color-input-error;
}
[data-type='re_engagement'] .mailpoet-newsletter-type-image {

View File

@ -161,3 +161,12 @@ ul.sending-method-benefits {
.mailpoet_install_premium_message {
margin-bottom: $grid-gap-medium;
}
.mailpoet-verify-key-button {
height: 36px;
}
.mailpoet-premium-key-toggle {
height: 34px;
padding: 0 10px !important;
}

View File

@ -559,38 +559,3 @@ h2.mailpoet-heading {
font-size: 85%;
}
}
// screen-reader-text CSS class only exists within the WordPress environment
// the class does not exist when using iFrame forms due to these being used outside WordPress
// prefixing with mailpoet-* to not interfere with the default WordPress screen-reader-text class
.mailpoet-screen-reader-text {
border: 0;
clip: rect(1px, 1px, 1px, 1px);
-webkit-clip-path: inset(50%);
clip-path: inset(50%);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
word-wrap: normal !important;
}
.mailpoet-screen-reader-text:focus {
background-color: #ddd;
clip: auto !important;
-webkit-clip-path: none;
clip-path: none;
color: #444;
display: block;
font-size: 1em;
height: auto;
line-height: normal;
padding: 15px 23px 14px;
right: 5px;
text-decoration: none;
top: 5px;
width: auto;
z-index: 100000;
}

View File

@ -10,3 +10,15 @@
}
}
}
// WP registration form
form#registerform .g-recaptcha:not([data-size='invisible']) {
scale: 0.9;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
}
// WC registration form
form.woocommerce-form-register .g-recaptcha {
padding-inline-start: 3px;
}

View File

@ -16,7 +16,7 @@ textarea.parsley-error {
.parsley-errors-list {
color: #900;
font-size: 13px;
font-size: 0.8rem;
line-height: 1em;
list-style-type: none;
margin: 8px 0 3px;

View File

@ -1,5 +1,3 @@
$beamer-dot-size: 8px;
.mailpoet-top-bar {
align-items: center;
background-color: $color-white;
@ -83,7 +81,7 @@ $beamer-dot-size: 8px;
}
}
.mailpoet-top-bar-beamer {
.mailpoet-top-bar-tutorial {
align-items: center;
background-color: $color-white;
border: none;
@ -96,6 +94,7 @@ $beamer-dot-size: 8px;
position: relative;
text-align: center;
text-decoration: none;
top: 4px;
width: 75px;
svg {
@ -103,15 +102,3 @@ $beamer-dot-size: 8px;
width: 100%;
}
}
.mailpoet-top-bar-beamer-dot:before {
background: $color-editor-warning;
border-radius: $beamer-dot-size;
content: '';
display: block;
height: $beamer-dot-size;
position: absolute;
right: 2px;
top: 2px;
width: $beamer-dot-size;
}

View File

@ -21,7 +21,7 @@
&:focus {
~ .mailpoet-form-checkbox-control {
border: 2px solid $color-input-border;
border-color: $color-input-border-focus;
}
}
}

View File

@ -21,7 +21,7 @@
&:focus {
~ .mailpoet-form-radio-control {
border: 2px solid $color-input-border;
border-color: $color-input-border-focus;
}
}
}

View File

@ -9,9 +9,15 @@
input {
height: 1px;
opacity: 0;
position: absolute;
visibility: hidden;
width: 1px;
&:focus {
~ .mailpoet-form-toggle-control {
border-color: $color-input-border-focus;
}
}
}
}

View File

@ -22,9 +22,16 @@
input {
height: 1px;
opacity: 0;
position: absolute;
visibility: hidden;
width: 1px;
&:focus {
~ .mailpoet-form-yesno-control {
box-shadow: 0 0 0 1px $color-input-border-focus;
z-index: 1;
}
}
}
}

View File

@ -110,10 +110,3 @@ span.mailpoet-gap-half {
height: 6px;
width: 8px;
}
.mailpoet-is-dragging {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}

View File

@ -4,6 +4,36 @@
line-height: $line-height;
}
h1,
h2,
h3,
h4,
h5,
h6,
caption,
figcaption {
// https://developer.chrome.com/docs/css-ui/css-text-wrap-balance
text-wrap: balance;
// Skip in email editor to preserve WYSIWYG functionality
.mailpoet_newsletter_wrapper & {
text-wrap: wrap;
}
}
p,
ul,
ol,
blockquote {
// https://developer.chrome.com/blog/css-text-wrap-pretty/
text-wrap: pretty;
// Skip in email editor to preserve WYSIWYG functionality
.mailpoet_newsletter_wrapper & {
text-wrap: wrap;
}
}
.admin_page_mailpoet-form-editor #wpbody {
color: inherit;
}

View File

@ -87,7 +87,6 @@
@import 'components-plugin/newsletter-types';
@import 'components-plugin/newsletter-template-styles';
@import 'components-plugin/welcome-wizard';
@import 'components-plugin/feature-announcement';
@import 'components-plugin/newsletter-congratulate';
@import 'components-plugin/discounts';
@import 'components-plugin/review-request';

View File

@ -31,6 +31,7 @@ $color-tertiary-hover: darken($color-tertiary, 10%);
$color-tertiary-light: #dcdcde;
$color-grey-0: #f6f7f7;
$color-tertiary-light-hover: darken($color-tertiary-light, 10%);
$color-tertiary-light-focus: #777;
$color-tertiary-light-background: rgba($color-tertiary-light, 0.3);
$color-destructive: #b52727;
$color-destructive-hover: #a02222;
@ -46,6 +47,7 @@ $color-text-dark: #2c3338;
// Form colors
$color-input-background: #fdfdff;
$color-input-border: $color-tertiary-light-hover;
$color-input-border-focus: $color-tertiary-light-focus;
$color-input-error: #f00;
$color-input-success: #7ed321;

View File

@ -53,7 +53,7 @@ function exportMixpanel() {
if (
window.mailpoet_analytics_enabled &&
window.MailPoet.libs3rdPartyEnabled
window.mailpoet_3rd_party_libs_enabled
) {
window.MailPoet.trackEvent = track;
} else {
@ -104,11 +104,30 @@ function cacheEvent(forced, name, data, options, callback) {
}
export function initializeMixpanelWhenLoaded() {
if (typeof window.mixpanel === 'object') {
const MAX_RETRY = 5;
let intervalId;
let retryCount = 0;
const setupMixpanel = () => {
exportMixpanel();
trackCachedEvents();
};
if (typeof window.mixpanel === 'object') {
setupMixpanel();
} else {
setTimeout(initializeMixpanelWhenLoaded, 100);
intervalId = setInterval(() => {
if (typeof window.mixpanel === 'object') {
clearInterval(intervalId);
setupMixpanel();
} else {
retryCount += 1;
}
if (retryCount > MAX_RETRY) {
clearInterval(intervalId);
}
}, 100);
}
}

View File

@ -1,33 +0,0 @@
import classnames from 'classnames';
import { MailPoet } from 'mailpoet';
import { withFeatureAnnouncement } from './with-feature-announcement';
type Props = {
hasNews: boolean;
onBeamerClick: () => void;
};
function FeatureAnnouncementComponent({ hasNews, onBeamerClick }: Props) {
const buttonClasses = classnames(
'button mailpoet_feature_announcement_button',
hasNews ? 'mailpoet_feature_announcement_dot' : '',
);
return (
<div className="mailpoet_feature_announcement">
<button
type="button"
onClick={onBeamerClick}
className={buttonClasses}
title={MailPoet.I18n.t('whatsNew')}
>
<span className="mailpoet_feature_announcement_icon dashicons dashicons-carrot" />
</button>
<span id="beamer-empty-element" />
</div>
);
}
const FeatureAnnouncement = withFeatureAnnouncement(
FeatureAnnouncementComponent,
);
export { FeatureAnnouncement };

View File

@ -1,111 +0,0 @@
import { ComponentType, FC } from 'react';
import { MailPoet } from 'mailpoet';
import ReactStringReplace from 'react-string-replace';
import jQuery from 'jquery';
import { noop } from 'lodash';
interface FeatureAnnouncementWindow extends Window {
Beamer: {
show: () => void;
};
mailpoet_feature_announcement_has_news: boolean;
mailpoet_update_available: boolean;
beamer_config: {
product_id: string;
selector: string;
language: string;
callback: () => void;
filter?: string;
};
mailpoet_user_locale: string;
}
declare let window: FeatureAnnouncementWindow;
export const withFeatureAnnouncement = <P extends Record<string, unknown>>(
Component: ComponentType<P>,
): FC<Omit<P, 'hasNews' | 'onBeamerClick'>> => {
const isBeamerInitialized = () => typeof window.Beamer !== 'undefined';
let showDot = window.mailpoet_feature_announcement_has_news;
let beamerCallback;
function showPluginUpdateNotice() {
if (
!window.mailpoet_update_available ||
document.getElementById('mailpoet_update_notice')
) {
return;
}
const updateMailPoetNotice = ReactStringReplace(
MailPoet.I18n.t('updateMailPoetNotice'),
/\[link\](.*?)\[\/link\]/,
(match) => `<a href="update-core.php">${match}</a>`,
).join('');
jQuery('#beamerOverlay').append(
`<p id="mailpoet_update_notice" class="mailpoet_in_beamer_update_notice">${updateMailPoetNotice}</p>`,
);
}
function updateLastAnnouncementSeenValue() {
const data = { last_announcement_seen: Math.floor(Date.now() / 1000) };
void MailPoet.Ajax.post({
api_version: MailPoet.apiVersion,
endpoint: 'user_flags',
action: 'set',
data,
});
}
function loadBeamer() {
window.beamer_config = {
product_id: 'VvHbhYWy7118',
selector: '#beamer-empty-element',
language: window.mailpoet_user_locale,
callback: beamerCallback,
};
if (MailPoet.isWoocommerceActive) {
window.beamer_config.filter = 'woocommerce';
}
MailPoet.Modal.loading(true);
window.mailpoet_feature_announcement_has_news = false;
const s = document.createElement('script');
s.type = 'text/javascript';
s.src = 'https://app.getbeamer.com/js/beamer-embed.js';
document.getElementsByTagName('body')[0].appendChild(s);
}
function showBeamer(event = null) {
if (event) {
event.preventDefault();
}
if (!isBeamerInitialized()) {
loadBeamer();
return;
}
showDot = false;
beamerCallback = noop; // We show Beamer panel only on first callback after initialization
MailPoet.Modal.loading(false);
window.Beamer.show();
updateLastAnnouncementSeenValue();
showPluginUpdateNotice();
}
beamerCallback = () => {
if (!isBeamerInitialized()) {
return;
}
showBeamer();
};
return function withFeatureAnnouncementRenderer({
...props
}: Omit<P, 'hasNews' | 'onBeamerClick'>) {
return (
<Component
{...(props as P)}
onBeamerClick={(e) => showBeamer(e)}
hasNews={showDot}
/>
);
};
};

View File

@ -16,7 +16,11 @@ export type ApiError = {
export const initializeApi = () => {
apiFetch.use((options, next) => {
if (options.path && options.path.startsWith('/wc-analytics/')) {
if (
options.path &&
(options.path.startsWith('/wc-analytics/') ||
options.path.startsWith('/wp/v2/'))
) {
return apiFetch.createRootURLMiddleware(`${api.root}/`)(options, next);
}
return apiFetch.createRootURLMiddleware(apiUrl)(options, next);

View File

@ -1,7 +1,7 @@
import { useEffect, useState } from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import { TopBarWithBeamer } from 'common/top-bar/top-bar';
import { TopBarWithBoundary } from 'common/top-bar/top-bar';
import { SlotFillProvider } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { registerTranslations } from 'common';
@ -72,7 +72,7 @@ function Automations(): JSX.Element {
return (
<>
<TopBarWithBeamer />
<TopBarWithBoundary />
<GlobalNotices />
<Notices />
<MssAccessNotices />

View File

@ -3,14 +3,23 @@ import { FlowSeparator } from './flow-separator';
import { Step as StepData } from './types';
type Props = {
stepData: StepData;
previousStepData: StepData;
index: number;
nextStepData?: StepData;
};
export function FlowEnding({ stepData, index }: Props): JSX.Element {
export function FlowEnding({
previousStepData,
index,
nextStepData,
}: Props): JSX.Element {
return (
<div className="mailpoet-automation-editor-step-wrapper">
<FlowSeparator stepData={stepData} index={index} />
<FlowSeparator
previousStepData={previousStepData}
nextStepData={nextStepData}
index={index}
/>
<Icon
className="mailpoet-automation-editor-automation-end"
icon={check}

View File

@ -6,8 +6,9 @@ import { Step as StepData } from './types';
import { RenderStepSeparatorType } from '../../../types/filters';
type Props = {
stepData: StepData;
previousStepData: StepData;
index: number;
nextStepData?: StepData;
};
export function FlowSeparator(props: Props): JSX.Element {
@ -35,5 +36,9 @@ export function FlowSeparator(props: Props): JSX.Element {
),
[context],
);
return renderSeparator(props.stepData, props.index);
return renderSeparator(
props.previousStepData,
props.index,
props.nextStepData,
);
}

View File

@ -40,13 +40,24 @@ export function Flow({ stepData, row }: Props): JSX.Element {
return nextStepData ? (
<div key={id}>
{row > 0 && <FlowSeparator stepData={stepData} index={i} />}
{row > 0 && (
<FlowSeparator
previousStepData={stepData}
index={i}
nextStepData={nextStepData}
/>
)}
<FlowStep stepData={nextStepData} index={i} />
<Flow stepData={nextStepData} row={row + 1} />
</div>
) : (
// eslint-disable-next-line react/no-array-index-key
<FlowEnding key={i} stepData={stepData} index={i} />
<FlowEnding
// eslint-disable-next-line react/no-array-index-key
key={i}
previousStepData={stepData}
index={i}
nextStepData={nextStepData}
/>
);
})}
</div>

View File

@ -143,6 +143,7 @@ export function* activate() {
return {
type: 'ACTIVATE',
automation: data?.data ?? automation,
saved: !!data?.data,
} as const;
}

View File

@ -41,11 +41,15 @@ export function reducer(state: State, action): State {
savedState: 'saved',
};
case 'ACTIVATE':
return {
...state,
automationData: action.automation,
savedState: 'saved',
};
return action.saved
? {
...state,
automationData: action.automation,
savedState: 'saved',
}
: {
...state,
};
case 'DEACTIVATE':
return {
...state,

View File

@ -50,6 +50,7 @@ export function initHooks() {
return function StatisticSeparatorWrapper(
previousStepData: StepData,
index: number,
nextStepData: StepData,
) {
return (
<>
@ -62,7 +63,11 @@ export function initHooks() {
}
/>
)}
<StatisticSeparator previousStep={previousStepData} index={index} />
<StatisticSeparator
previousStep={previousStepData}
nextStep={nextStepData}
index={index}
/>
</>
);
};

View File

@ -8,11 +8,13 @@ import { Step } from '../../../../../../editor/components/automation/types';
type Props = {
previousStep: Step;
index: number;
nextStep?: Step;
};
export function StatisticSeparator({
previousStep,
index,
nextStep,
}: Props): JSX.Element | null {
const { section, stepType } = useSelect(
(s) => ({
@ -52,15 +54,34 @@ export function StatisticSeparator({
);
}
const flow = data.step_data?.flow;
const value = flow !== undefined ? flow[previousStep.id] ?? 0 : 0;
const completed = data.step_data?.completed || {};
const failed = data.step_data?.failed || {};
const waiting = data.step_data?.waiting || {};
const calculateTotals = (id) =>
(completed[id] ?? 0) + (failed[id] ?? 0) + (waiting[id] ?? 0);
let totalEntered = 0;
if (nextStep) {
totalEntered = calculateTotals(nextStep.id);
} else if (previousStep.next_steps.length === 2) {
// When there is no next step and the previous step has 2+ next steps we are
// in an empty if/else branch. To calculate the total we need to subtract
// totalEntered of the sibling step from totalEntered of previousStep
const siblingStep = previousStep.next_steps.find((step) => step.id);
const totalEnteredSibling = siblingStep
? calculateTotals(siblingStep.id)
: 0;
const totalEnteredPrevious = completed[previousStep.id] ?? 0;
totalEntered = totalEnteredPrevious - totalEnteredSibling;
} else {
totalEntered = completed[previousStep.id] ?? 0;
}
const percent =
data.step_data.total > 0
? Math.round((value / data.step_data.total) * 100)
? Math.round((totalEntered / data.step_data.total) * 100)
: 0;
const formattedValue = Intl.NumberFormat(locale.toString(), {
notation: 'compact',
}).format(value);
}).format(totalEntered);
const formattedPercent = Intl.NumberFormat(locale.toString(), {
style: 'percent',
}).format(percent / 100);

View File

@ -2,7 +2,7 @@ import { createRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import { dispatch, select, useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { TopBarWithBeamer } from '../../../../common/top-bar/top-bar';
import { TopBarWithBoundary } from '../../../../common/top-bar/top-bar';
import { Notices } from '../../../listing/components/notices';
import { Header } from './components/header';
import { Overview } from './components/overview';
@ -49,7 +49,7 @@ function TopBarWithBreadcrumb(): JSX.Element {
}));
return (
<TopBarWithBeamer>
<TopBarWithBoundary>
<p className="mailpoet-automation-analytics-title">
<a href={MailPoet.urls.automationListing}>
{__('Automations', 'mailpoet')}
@ -57,7 +57,7 @@ function TopBarWithBreadcrumb(): JSX.Element {
<strong>{automation.name}</strong>
<AutomationStatus status={automation.status} />
</p>
</TopBarWithBeamer>
</TopBarWithBoundary>
);
}

View File

@ -167,7 +167,7 @@ export type StepFlowData = {
total: number;
waiting: Record<string, number> | undefined;
failed: Record<string, number> | undefined;
flow: Record<string, number> | undefined;
completed: Record<string, number> | undefined;
};
export type AutomationFlowSectionData = SectionData & {

View File

@ -3,6 +3,7 @@ import { Step } from '../../../../../editor/components/automation/types';
import { storeName } from '../../../../../editor/store';
const transactionalTriggers = [
'mailpoet:custom-trigger',
'woocommerce:order-status-changed',
'woocommerce:order-created',
'woocommerce:order-completed',
@ -15,6 +16,9 @@ const transactionalTriggers = [
'woocommerce-subscriptions:subscription-status-changed',
'woocommerce-subscriptions:trial-ended',
'woocommerce-subscriptions:trial-started',
'woocommerce:buys-from-a-tag',
'woocommerce:buys-from-a-category',
'woocommerce:buys-a-product',
];
export function isTransactional(step: Step): boolean {

View File

@ -7,6 +7,7 @@ import { step as AbandonedCartTrigger } from './steps/abandoned-cart';
import { MailPoet } from '../../../mailpoet';
import { step as BuysAProductTrigger } from './steps/buys-a-product';
import { step as BuysFromACategory } from './steps/buys-from-a-category';
import { step as BuysFromATag } from './steps/buys-from-a-tag';
import { step as MadeAReview } from './steps/made-a-review';
// Insert new imports here
@ -21,6 +22,7 @@ export const initialize = (): void => {
registerStepType(AbandonedCartTrigger);
registerStepType(BuysAProductTrigger);
registerStepType(BuysFromACategory);
registerStepType(BuysFromATag);
registerStepType(MadeAReview);
// Insert new steps here
};

View File

@ -0,0 +1,86 @@
import { useEffect, useMemo, useState } from 'react';
import { Search } from '@woocommerce/components';
import { __ } from '@wordpress/i18n';
import { PanelBody } from '@wordpress/components';
import apiFetch from '@wordpress/api-fetch';
import { addQueryArgs } from '@wordpress/url';
import { dispatch, useSelect } from '@wordpress/data';
import { PlainBodyTitle } from '../../../../../editor/components';
import { storeName } from '../../../../../editor/store';
import { OrderStatusPanel } from '../../order-status-changed/edit/order-status-panel';
import autocompleter from './tag-autocompleter';
type Tag = {
key: string | number;
label?: string;
};
async function fetchTags(include: number[], callback: (tags: Tag[]) => void) {
const path = addQueryArgs('/wp/v2/product_tag/', { include });
const data: { id: number; name: string }[] = await apiFetch({
path,
method: 'GET',
});
callback(data.map((item) => ({ key: item?.id, label: item?.name })));
}
export function Edit(): JSX.Element {
const [current, setCurrent] = useState<Tag[]>([]);
const { selectedStep } = useSelect((select) => ({
selectedStep: select(storeName).getSelectedStep(),
}));
const tagIds: number[] = useMemo(
() => (selectedStep.args?.tag_ids as number[]) ?? [],
[selectedStep],
);
const [isBusy, setIsBusy] = useState(tagIds.length > 0);
useEffect(() => {
if (!isBusy) {
return;
}
void fetchTags(tagIds, (tags: Tag[]) => {
setCurrent(tags);
setIsBusy(false);
});
}, [isBusy, tagIds]);
return (
<>
<PanelBody opened>
<PlainBodyTitle title={__('Tags', 'mailpoet')} />
<Search
disabled={isBusy}
type="custom"
autocompleter={autocompleter}
className={`mailpoet-product-search ${isBusy ? 'is-busy' : ''}`}
placeholder={__('Search for a tag', 'mailpoet')}
selected={current}
onChange={(items: Tag[]) => {
setCurrent(items);
void dispatch(storeName).updateStepArgs(
selectedStep.id,
'tag_ids',
items.map((item) => item.key),
);
}}
multiple
inlineTags
/>
</PanelBody>
<OrderStatusPanel
label={__('Order settings', 'mailpoet')}
showFrom={false}
showTo
toLabel={__('Order status', 'mailpoet')}
onChange={(status, property) => {
void dispatch(storeName).updateStepArgs(
selectedStep.id,
property,
status,
);
}}
/>
</>
);
}

View File

@ -0,0 +1,67 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { addQueryArgs } from '@wordpress/url';
import apiFetch from '@wordpress/api-fetch';
import { AutoCompleter } from '@woocommerce/components/build-types/search/autocompleters';
const tagAutoCompleter: AutoCompleter = {
name: 'tags',
className: 'woocommerce-search__product-result',
options(search) {
const query = search
? {
search,
per_page: 10,
orderby: 'count',
}
: {};
return apiFetch({
path: addQueryArgs('/wp/v2/product_tag', query),
});
},
isDebounced: true,
getOptionIdentifier(tag) {
return tag.id as number;
},
getOptionKeywords(tag) {
return [tag.name] as string[];
},
getFreeTextOptions(query) {
const label = (
<span key="name" className="woocommerce-search__result-name">
{__('Search results', 'mailpoet')}
</span>
);
const titleOption = {
key: 'title',
label,
value: { id: query, name: query },
};
return [titleOption];
},
getOptionLabel(tag) {
return (
<span
key="name"
className="woocommerce-search__result-name"
aria-label={tag.name}
>
{tag.name}
</span>
);
},
// This is slightly different than gutenberg/Autocomplete, we don't support different methods
// of replace/insertion, so we can just return the value.
getOptionCompletion(tag) {
const value = {
key: tag.id,
label: tag.name,
};
return value;
},
};
export default tagAutoCompleter;

View File

@ -0,0 +1,26 @@
export function Icon(): JSX.Element {
return (
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5.73173 4.00134C5.8081 3.03517 6.61579 2.27551 7.60166 2.27551C8.58753 2.27551 9.39522 3.03517 9.47159 4.00134H10.1904C10.7479 4.00134 11.2033 4.45681 11.2033 5.01426V10.1917C11.2033 10.7492 10.7479 11.2047 10.1904 11.2047H5.01292C4.45547 11.2047 4 10.7492 4 10.1917V5.01426C4 4.45681 4.45547 4.00134 5.01292 4.00134H5.73173ZM7.60166 3.43843C7.36389 3.43843 7.15161 3.55664 7.02145 3.73861C6.96586 3.81633 6.92553 3.90533 6.90474 4.00134H8.29858C8.27779 3.90533 8.23746 3.81633 8.18187 3.73861C8.05171 3.55664 7.83943 3.43843 7.60166 3.43843ZM5.16291 5.16426V9.65285C5.16291 9.86763 5.33703 10.0417 5.55181 10.0417H9.65151C9.86629 10.0417 10.0404 9.86763 10.0404 9.65285V5.16426H9.47749V5.87717C9.47749 6.19732 9.21618 6.45863 8.89603 6.45863C8.57589 6.45863 8.31458 6.19732 8.31458 5.87717V5.16426H6.88875V5.87717C6.88875 6.19732 6.62743 6.45863 6.30729 6.45863C5.98714 6.45863 5.72583 6.19732 5.72583 5.87717V5.16426H5.16291Z"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M13.5858 4.58722C13.9609 4.21215 14.4696 4.00143 15 4.00143H18C18.5304 4.00143 19.0391 4.21215 19.4142 4.58722C19.7893 4.96229 20 5.471 20 6.00143V9.00143C20 9.53187 19.7893 10.0406 19.4142 10.4156C19.0391 10.7907 18.5304 11.0014 18 11.0014H15C14.4696 11.0014 13.9609 10.7907 13.5858 10.4156C13.2107 10.0406 13 9.53187 13 9.00143V6.00143C13 5.471 13.2107 4.96229 13.5858 4.58722ZM15 5.50143H18C18.1326 5.50143 18.2598 5.55411 18.3536 5.64788C18.4473 5.74165 18.5 5.86883 18.5 6.00143V9.00143C18.5 9.13404 18.4473 9.26122 18.3536 9.35499C18.2598 9.44876 18.1326 9.50143 18 9.50143H15C14.8674 9.50143 14.7402 9.44876 14.6464 9.35499C14.5527 9.26122 14.5 9.13404 14.5 9.00143V6.00143C14.5 5.86883 14.5527 5.74165 14.6464 5.64788C14.7402 5.55411 14.8674 5.50143 15 5.50143Z"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M13.5858 13.5844C13.9609 13.2093 14.4696 12.9986 15 12.9986H18C18.5304 12.9986 19.0391 13.2093 19.4142 13.5844C19.7893 13.9594 20 14.4681 20 14.9986V17.9986C20 18.529 19.7893 19.0377 19.4142 19.4128C19.0391 19.7879 18.5304 19.9986 18 19.9986H15C14.4696 19.9986 13.9609 19.7879 13.5858 19.4128C13.2107 19.0377 13 18.529 13 17.9986V14.9986C13 14.4681 13.2107 13.9594 13.5858 13.5844ZM15 14.4986H18C18.1326 14.4986 18.2598 14.5513 18.3536 14.645C18.4473 14.7388 18.5 14.866 18.5 14.9986V17.9986C18.5 18.1312 18.4473 18.2584 18.3536 18.3521C18.2598 18.4459 18.1326 18.4986 18 18.4986H15C14.8674 18.4986 14.7402 18.4459 14.6464 18.3521C14.5527 18.2584 14.5 18.1312 14.5 17.9986V14.9986C14.5 14.866 14.5527 14.7388 14.6464 14.645C14.7402 14.5513 14.8674 14.4986 15 14.4986Z"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M4.58579 13.5844C4.21071 13.9594 4 14.4681 4 14.9986V17.9986C4 18.529 4.21071 19.0377 4.58579 19.4128C4.96086 19.7879 5.46957 19.9986 6 19.9986H9C9.53043 19.9986 10.0391 19.7879 10.4142 19.4128C10.7893 19.0377 11 18.529 11 17.9986V14.9986C11 14.4681 10.7893 13.9594 10.4142 13.5844C10.0391 13.2093 9.53043 12.9986 9 12.9986H6C5.46957 12.9986 4.96086 13.2093 4.58579 13.5844ZM9 14.4986H6C5.86739 14.4986 5.74021 14.5513 5.64645 14.645C5.55268 14.7388 5.5 14.866 5.5 14.9986V17.9986C5.5 18.1312 5.55268 18.2584 5.64645 18.3521C5.74021 18.4459 5.86739 18.4986 6 18.4986H9C9.13261 18.4986 9.25979 18.4459 9.35355 18.3521C9.44732 18.2584 9.5 18.1312 9.5 17.9986V14.9986C9.5 14.866 9.44732 14.7388 9.35355 14.645C9.25979 14.5513 9.13261 14.4986 9 14.4986Z"
/>
</svg>
);
}

View File

@ -0,0 +1,38 @@
import { __ } from '@wordpress/i18n';
import { StepType } from '../../../../editor/store';
import { Edit } from './edit';
import { Icon } from './icon';
const keywords = [
// translators: noun, used as a search keyword for "Customer buys from a tag" trigger
__('tag', 'mailpoet'),
// translators: verb, used as a search keyword for "Customer buys from a tag" trigger
__('buy', 'mailpoet'),
// translators: verb, used as a search keyword for "Customer buys from a tag" trigger
__('purchase', 'mailpoet'),
// translators: noun, used as a search keyword for "Customer buys from a tag" trigger
__('ecommerce', 'mailpoet'),
// translators: noun, used as a search keyword for "Customer buys from a tag" trigger
__('woocommerce', 'mailpoet'),
// translators: noun, used as a search keyword for "Customer buys from a tag" trigger
__('product', 'mailpoet'),
// translators: noun, used as a search keyword for "Customer buys from a tag" trigger
__('order', 'mailpoet'),
];
export const step: StepType = {
key: 'woocommerce:buys-from-a-tag',
group: 'triggers',
title: () => __('Customer buys from a tag', 'mailpoet'),
description: () =>
__(
'Start the automation when a customer buys a product from a tag.',
'mailpoet',
),
subtitle: () => __('Trigger', 'mailpoet'),
keywords,
foreground: '#2271b1',
background: '#f0f6fc',
icon: () => <Icon />,
edit: () => <Edit />,
} as const;

View File

@ -4,27 +4,27 @@ import { Icon } from './icon';
import { PremiumModalForStepEdit } from '../../../../components/premium-modal-steps-edit';
const keywords = [
// translators: noun, used as a search keyword for "Customer makes a review" trigger
// translators: noun, used as a search keyword for "Customer posts a review" trigger
__('review', 'mailpoet'),
// translators: verb, used as a search keyword for "Customer makes a review" trigger
// translators: verb, used as a search keyword for "Customer posts a review" trigger
__('buy', 'mailpoet'),
// translators: noun, used as a search keyword for "Customer makes a review" trigger
// translators: noun, used as a search keyword for "Customer posts a review" trigger
__('comment', 'mailpoet'),
// translators: noun, used as a search keyword for "Customer makes a review" trigger
// translators: noun, used as a search keyword for "Customer posts a review" trigger
__('ecommerce', 'mailpoet'),
// translators: noun, used as a search keyword for "Customer makes a review" trigger
// translators: noun, used as a search keyword for "Customer posts a review" trigger
__('woocommerce', 'mailpoet'),
// translators: noun, used as a search keyword for "Customer makes a review" trigger
// translators: noun, used as a search keyword for "Customer posts a review" trigger
__('product', 'mailpoet'),
// translators: noun, used as a search keyword for "Customer makes a review" trigger
// translators: noun, used as a search keyword for "Customer posts a review" trigger
__('order', 'mailpoet'),
];
export const step: StepType = {
key: 'woocommerce:made-a-review',
group: 'triggers',
title: () => __('Customer makes a review', 'mailpoet'),
title: () => __('Customer posts a review', 'mailpoet'),
description: () =>
__('Start the automation when a customer makes a review.', 'mailpoet'),
__('Start the automation when a customer posts a review.', 'mailpoet'),
subtitle: () => __('Trigger', 'mailpoet'),
keywords,

View File

@ -3,7 +3,7 @@ import { __ } from '@wordpress/i18n';
import { registerTranslations } from 'common';
import { automationTemplateCategories, automationTemplates } from './config';
import { initializeApi } from '../api';
import { TopBarWithBeamer } from '../../common/top-bar/top-bar';
import { TopBarWithBoundary } from '../../common/top-bar/top-bar';
import { FromScratchButton } from './components/from-scratch';
import { BackButton, PageHeader } from '../../common/page-header';
import { MailPoet } from '../../mailpoet';
@ -50,7 +50,7 @@ function Templates(): JSX.Element {
return (
<div className="mailpoet-main-container">
<TopBarWithBeamer />
<TopBarWithBoundary />
<PageHeader
heading={__('Start with a template', 'mailpoet')}
headingPrefix={

View File

@ -37,8 +37,9 @@ export type RenderStepFooterType = JSX.Element | null;
// mailpoet.automation.render_step_separator
export type RenderStepSeparatorType = (
step: Step,
previousStep: Step,
index: number,
nextStep?: Step,
) => JSX.Element;
// mailpoet.automation.editor.create_store

View File

@ -1,4 +1,4 @@
import { __, _x } from '@wordpress/i18n';
import { __, sprintf } from '@wordpress/i18n';
import { PlacesType } from 'react-tooltip';
import { Badge } from './badge';
@ -10,47 +10,59 @@ type StatsBadgeProps = {
isInverted?: boolean;
};
const stats = {
const getStats = () => ({
opened: {
badgeRanges: [30, 10, 0],
badgeTypes: ['excellent', 'good', 'critical'],
tooltipText: {
excellent: _x('above 30%', 'Excellent open rate', 'mailpoet'),
good: _x('between 10 and 30%', 'Good open rate', 'mailpoet'),
critical: _x('under 10%', 'Critical open rate', 'mailpoet'),
// translators: Shows a percentage range, "above 30%". Used in contexts like open, click, bounce, or unsubscribe rates.
excellent: sprintf(__('above %s%%', 'mailpoet'), 30),
// translators: Shows a percentage range, "between 10% and 30%". Used in contexts like open, click, bounce, or unsubscribe rates.
good: sprintf(__('between %s%% and %s%%', 'mailpoet'), 10, 30),
// translators: Shows a percentage range, "below 10%". Used in contexts like open, click, bounce, or unsubscribe rates.
critical: sprintf(__('below %s%%', 'mailpoet'), 10),
},
},
clicked: {
badgeRanges: [3, 1, 0],
badgeTypes: ['excellent', 'good', 'critical'],
tooltipText: {
excellent: _x('above 3%', 'Excellent click rate', 'mailpoet'),
good: _x('between 1 and 3%', 'Good click rate', 'mailpoet'),
critical: _x('under 1%', 'Critical click rate', 'mailpoet'),
// translators: Shows a percentage range, "above 30%". Used in contexts like open, click, bounce, or unsubscribe rates.
excellent: sprintf(__('above %s%%', 'mailpoet'), 3),
// translators: Shows a percentage range, "between 10% and 30%". Used in contexts like open, click, bounce, or unsubscribe rates.
good: sprintf(__('between %s%% and %s%%', 'mailpoet'), 1, 3),
// translators: Shows a percentage range, "below 10%". Used in contexts like open, click, bounce, or unsubscribe rates.
critical: sprintf(__('below %s%%', 'mailpoet'), 1),
},
},
bounced: {
badgeRanges: [1.5, 0.5, 0],
badgeTypes: ['critical', 'good', 'excellent'],
tooltipText: {
excellent: _x('below 0.5%', 'Excellent bounce rate', 'mailpoet'),
good: _x('between 0.5% and 1.5%', 'Good bounce rate', 'mailpoet'),
critical: _x('above 1.5%', 'Critical bounce rate', 'mailpoet'),
// translators: Shows a percentage range, "below 10%". Used in contexts like open, click, bounce, or unsubscribe rates.
excellent: sprintf(__('below %s%%', 'mailpoet'), 0.5),
// translators: Shows a percentage range, "between 10% and 30%". Used in contexts like open, click, bounce, or unsubscribe rates.
good: sprintf(__('between %s%% and %s%%', 'mailpoet'), 0.5, 1.5),
// translators: Shows a percentage range, "above 30%". Used in contexts like open, click, bounce, or unsubscribe rates.
critical: sprintf(__('above %s%%', 'mailpoet'), 1.5),
},
},
unsubscribed: {
badgeRanges: [0.7, 0.3, 0],
badgeTypes: ['critical', 'good', 'excellent'],
tooltipText: {
excellent: _x('Below 0.3%', 'Excellent unsubscribe rate', 'mailpoet'),
good: _x('between 0.3% and 0.7%', 'Good unsubscribe rate', 'mailpoet'),
critical: _x('above 0.7%', 'Critical unsubscribe rate', 'mailpoet'),
// translators: Shows a percentage range, "below 10%". Used in contexts like open, click, bounce, or unsubscribe rates.
excellent: sprintf(__('below %s%%', 'mailpoet'), 0.3),
// translators: Shows a percentage range, "between 10% and 30%". Used in contexts like open, click, bounce, or unsubscribe rates.
good: sprintf(__('between %s%% and %s%%', 'mailpoet'), 0.3, 0.7),
// translators: Shows a percentage range, "above 30%". Used in contexts like open, click, bounce, or unsubscribe rates.
critical: sprintf(__('above %s%%', 'mailpoet'), 0.7),
},
},
};
});
export const getBadgeType = (statName, rate) => {
const stat = stats[statName] || null;
const stat = getStats()[statName] || null;
if (!stat) {
return null;
}
@ -91,7 +103,7 @@ function StatsBadge(props: StatsBadgeProps) {
return null;
}
const stat = stats[props.stat] || null;
const stat = getStats()[props.stat] || null;
if (!stat) {
return null;
}

View File

@ -1,21 +1,40 @@
import { Input } from 'common/index';
import { _x } from '@wordpress/i18n';
import { Button, Input } from 'common/index';
import { useAction, useSelector } from 'settings/store/hooks';
import { useState } from 'react';
type KeyInputPropType = {
placeholder?: string;
isFullWidth?: boolean;
forceRevealed?: boolean;
};
export function KeyInput({
placeholder,
isFullWidth = false,
forceRevealed = false,
}: KeyInputPropType) {
const state = useSelector('getKeyActivationState')();
const setState = useAction('updateKeyActivationState');
const [isRevealed, setIsRevealed] = useState(false);
const inputType = forceRevealed || isRevealed ? 'text' : 'password';
const toggleButton = !forceRevealed && (
<Button
className="mailpoet-premium-key-toggle"
variant="tertiary"
onClick={() => setIsRevealed(!isRevealed)}
>
{isRevealed
? // translators: Used as a button to show or hide the premium key
_x('Hide', 'verb', 'mailpoet')
: // translators: Used as a button to show or hide the premium key
_x('Show', 'verb', 'mailpoet')}
</Button>
);
return (
<Input
type="text"
type={inputType}
id="mailpoet_premium_key"
name="premium[premium_key]"
placeholder={placeholder}
@ -29,6 +48,7 @@ export function KeyInput({
key: event.target.value.trim() || null,
})
}
iconEnd={toggleButton}
/>
);
}

View File

@ -1,4 +1,3 @@
import { action } from '_storybook/action';
import { TopBar } from '../top-bar';
export default {
@ -17,7 +16,7 @@ export function TopBarWithoutChildren() {
left: '0px',
}}
>
<TopBar hasNews={false} onBeamerClick={action('beamer click')} />
<TopBar />
</div>
);
}
@ -34,7 +33,7 @@ export function TopBarWithoutChildrenWithNews() {
left: '0px',
}}
>
<TopBar hasNews onBeamerClick={action('beamer click')} />
<TopBar />
</div>
);
}

View File

@ -1,4 +1,3 @@
import { action } from '_storybook/action';
import { TopBar } from '../top-bar';
import { Button } from '../../button/button';
@ -18,7 +17,7 @@ export function TopBarWithChildren() {
left: '0px',
}}
>
<TopBar hasNews={false} onBeamerClick={action('beamer click')}>
<TopBar>
<Button>Button</Button>
</TopBar>
</div>

View File

@ -1,22 +0,0 @@
export function BeamerIcon() {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M6 17V14.5002L6.00101 14.4997C7.10049 13.9995 7.90003 12.8998 8 11.7002V9.50016C8 7.96615 8.78223 6.62769 10.0309 5.95845C10.3288 5.79879 10.6533 5.67721 11 5.60016C10.9 5.50016 10.8 5.30016 10.8 5.10016C10.8 5.01146 10.8109 4.92493 10.8315 4.84189C10.95 4.36325 11.3887 4.00017 11.9 4.00017C11.9334 4.00017 11.9672 3.99696 12 4C12.0332 3.99688 12.0661 4.00004 12.1 4.00004C12.6113 4.00004 13.05 4.36313 13.1685 4.84177C13.1891 4.92481 13.2 5.01133 13.2 5.10004C13.2 5.30004 13.1 5.50004 13 5.60004C13.3467 5.67709 13.6712 5.79867 13.9691 5.95833C15.2178 6.62757 16 7.96602 16 9.50004V11.7C16.1 12.9 16.9 14.0002 18 14.5002V17.0002L6 17ZM17 16H7V15.148C8.2117 14.4742 8.98499 13.2218 9.09655 11.8831L9.1 9.50004C9.1 8.15301 9.99683 6.94434 11.3676 6.56356L11.7403 6.46006L12.0003 6.40228L12.2553 6.45896L12.6324 6.56368C14.0032 6.94446 14.9 8.15313 14.9 9.50016L14.9035 11.8832C15.015 13.2219 15.7883 14.4743 17 15.1481V16ZM12.0001 5.3601C12.221 5.3601 12.4001 5.18102 12.4001 4.9601C12.4001 4.73919 12.221 4.5601 12.0001 4.5601C11.7792 4.5601 11.6001 4.73919 11.6001 4.9601C11.6001 5.18102 11.7792 5.3601 12.0001 5.3601Z"
fill="#2C3338"
/>
<path
d="M13.8303 19C14.0017 18.7054 14.1 18.3637 14.1 18L9.9 18.0002C9.9 18.3638 9.99834 18.7055 10.1697 19.0002C10.5169 19.5968 11.1636 20.0002 11.9 20.0002C11.9339 20.0002 11.9677 19.9993 12.0012 19.9976C12.034 19.9992 12.0669 20 12.1 20C12.8364 20 13.4831 19.5967 13.8303 19Z"
fill="#2C3338"
/>
</svg>
);
}

View File

@ -1,62 +1,25 @@
import { ReactNode } from 'react';
import { __ } from '@wordpress/i18n';
import classnames from 'classnames';
import { withFeatureAnnouncement } from 'announcements/with-feature-announcement';
import { HideScreenOptions } from 'common/hide-screen-options/hide-screen-options';
import { MailPoetLogoResponsive } from './mailpoet-logo-responsive';
import { BeamerIcon } from './beamer-icon';
import { ScreenOptionsFix } from './screen-options-fix';
import { withBoundary } from '../error-boundary';
import { MailPoet } from '../../mailpoet';
type Props = {
children?: ReactNode;
hasNews?: boolean;
onBeamerClick?: () => void;
logoWithLink?: boolean;
hideScreenOptions?: boolean;
};
export function TopBar({
children,
hasNews,
onBeamerClick,
logoWithLink = true,
hideScreenOptions = false,
}: Props) {
const buttonClasses = classnames(
'mailpoet-top-bar-beamer',
hasNews ? 'mailpoet-top-bar-beamer-dot' : '',
);
return (
<div className="mailpoet-top-bar">
<MailPoetLogoResponsive withLink={logoWithLink} />
<div className="mailpoet-top-bar-children">{children}</div>
<div className="mailpoet-flex-grow" />
{onBeamerClick && MailPoet.libs3rdPartyEnabled && (
<div>
<a
role="button"
onClick={onBeamerClick}
className={buttonClasses}
title={__('Whats new', 'mailpoet')}
tabIndex={0}
onKeyDown={(event) => {
if (
['keydown', 'keypress'].includes(event.type) &&
['Enter', ' '].includes(event.key)
) {
event.preventDefault();
onBeamerClick();
}
}}
>
<BeamerIcon />
<span>{__('Updates', 'mailpoet')}</span>
</a>
<span id="beamer-empty-element" />
</div>
)}
<ScreenOptionsFix />
{hideScreenOptions && <HideScreenOptions />}
</div>
@ -64,4 +27,4 @@ export function TopBar({
}
TopBar.displayName = 'TopBar';
export const TopBarWithBeamer = withFeatureAnnouncement(withBoundary(TopBar));
export const TopBarWithBoundary = withBoundary(TopBar);

View File

@ -1,21 +0,0 @@
import { addFilter } from '@wordpress/hooks';
import { Block } from '@wordpress/blocks';
/**
* Disables Styles for button
* Currently we are not able to read these styles in renderer
*/
function enhanceButtonBlock() {
addFilter(
'blocks.registerBlockType',
'mailpoet-email-editor/change-button',
(settings: Block, name) => {
if (name === 'core/button') {
return { ...settings, styles: [] };
}
return settings;
},
);
}
export { enhanceButtonBlock };

View File

@ -1,28 +0,0 @@
import { addFilter } from '@wordpress/hooks';
import { Block } from '@wordpress/blocks';
/**
* Switch layout to reduced flex email layout
* Email render engine can't handle full flex layout se we need to switch to reduced flex layout
*/
function enhanceButtonsBlock() {
addFilter(
'blocks.registerBlockType',
'mailpoet-email-editor/change-buttons',
(settings: Block, name) => {
if (name === 'core/buttons') {
return {
...settings,
supports: {
...settings.supports,
layout: false, // disable block editor's layouts
__experimentalEmailFlexLayout: true, // enable MailPoet's reduced flex email layout
},
};
}
return settings;
},
);
}
export { enhanceButtonsBlock };

View File

@ -1,25 +0,0 @@
import { addFilter } from '@wordpress/hooks';
import { Block } from '@wordpress/blocks';
function enhanceColumnBlock() {
addFilter(
'blocks.registerBlockType',
'mailpoet-email-editor/change-column',
(settings: Block, name) => {
if (name === 'core/column') {
return {
...settings,
supports: {
...settings.supports,
background: {
backgroundImage: true,
},
},
};
}
return settings;
},
);
}
export { enhanceColumnBlock };

View File

@ -1,87 +0,0 @@
import { InspectorControls } from '@wordpress/block-editor';
import { createHigherOrderComponent } from '@wordpress/compose';
import { Block } from '@wordpress/blocks';
import { addFilter } from '@wordpress/hooks';
const columnsEditCallback = createHigherOrderComponent(
(BlockEdit) =>
function alterBlocksEdits(props) {
if (props.name !== 'core/columns') {
return <BlockEdit {...props} />;
}
// CSS sets opacity by the class is-disabled by the toggle component from the Gutenberg package
// To deactivating the input we use CSS pointer-events because we want to avoid JavaScript hacks
const deactivateToggleCss = `
.components-panel__body .components-toggle-control .components-form-toggle { opacity: 0.3; }
.components-panel__body .components-toggle-control .components-form-toggle__input { pointer-events: none; }
.components-panel__body .components-toggle-control label { pointer-events: none; }
`;
return (
<>
<BlockEdit {...props} />
<InspectorControls>
<style>{deactivateToggleCss}</style>
</InspectorControls>
</>
);
},
'columnsEditCallback',
);
function deactivateStackOnMobile() {
addFilter(
'editor.BlockEdit',
'mailpoet-email-editor/deactivate-stack-on-mobile',
columnsEditCallback,
);
}
/**
* Disables layout support for columns and column blocks because
* the default layout `flex` add gaps between columns that it is not possible to support in emails.
*/
function disableColumnsLayout() {
addFilter(
'blocks.registerBlockType',
'mailpoet-email-editor/disable-columns-layout',
(settings, name) => {
if (name === 'core/columns' || name === 'core/column') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return {
...settings,
supports: {
...settings.supports,
layout: false,
},
};
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return settings;
},
);
}
function enhanceColumnsBlock() {
addFilter(
'blocks.registerBlockType',
'mailpoet-email-editor/change-columns',
(settings: Block, name) => {
if (name === 'core/columns') {
return {
...settings,
supports: {
...settings.supports,
background: {
backgroundImage: true,
},
},
};
}
return settings;
},
);
}
export { deactivateStackOnMobile, disableColumnsLayout, enhanceColumnsBlock };

View File

@ -1,26 +0,0 @@
import { addFilter } from '@wordpress/hooks';
/**
* Disables layout support for group blocks because the default layout `flex` add gaps between columns that it is not possible to support in emails.
*/
function disableGroupVariations() {
addFilter(
'blocks.registerBlockType',
'mailpoet-email-editor/disable-group-variations',
(settings, name) => {
if (name === 'core/group') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return {
...settings,
variations: settings.variations.filter(
(variation) => variation.name === 'group',
),
};
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return settings;
},
);
}
export { disableGroupVariations };

View File

@ -1,61 +0,0 @@
import { InspectorControls } from '@wordpress/block-editor';
import { createHigherOrderComponent } from '@wordpress/compose';
import { addFilter } from '@wordpress/hooks';
import { Block } from '@wordpress/blocks';
const imageEditCallback = createHigherOrderComponent(
(BlockEdit) =>
function alterBlocksEdits(props) {
if (props.name !== 'core/image') {
return <BlockEdit {...props} />;
}
// Because we cannot support displaying the modal with image after clicking in the email we have to hide the toggle
const deactivateToggleCss = `
.components-tools-panel .components-toggle-control { display: none; }
`;
return (
<>
<BlockEdit {...props} />
<InspectorControls>
<style>{deactivateToggleCss}</style>
</InspectorControls>
</>
);
},
'imageEditCallback',
);
/**
* Because CSS property filter is not supported in almost 50% of email clients we have to disable it
*/
function disableImageFilter() {
addFilter(
'blocks.registerBlockType',
'mailpoet-email-editor/deactivate-image-filter',
(settings: Block, name) => {
if (name === 'core/image') {
return {
...settings,
supports: {
...settings.supports,
filter: {
duetone: false,
},
},
};
}
return settings;
},
);
}
function hideExpandOnClick() {
addFilter(
'editor.BlockEdit',
'mailpoet-email-editor/hide-expand-on-click',
imageEditCallback,
);
}
export { hideExpandOnClick, disableImageFilter };

View File

@ -1,58 +0,0 @@
import { addFilter } from '@wordpress/hooks';
import { Block } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
function Placeholder({ layoutClassNames }) {
const blockProps = useBlockProps({ className: layoutClassNames });
return (
<div {...blockProps}>
<p>{__('This is the Content block.', 'mailpoet')}</p>
<p>
{__(
'It will display all the blocks in the email content, which might be only simple text paragraphs. You can enrich your message with images, incorporate data through tables, explore different layout designs with columns, or use any other block type.',
'mailpoet',
)}
</p>
</div>
);
}
// Curried function to add a custom placeholder to the post content block, or just use the original Edit component.
function PostContentEdit(OriginalEditComponent) {
return function Edit({
context,
__unstableLayoutClassNames: layoutClassNames,
}) {
const { postId: contextPostId, postType: contextPostType } = context;
const hasContent = contextPostId && contextPostType;
if (hasContent) {
return (
<OriginalEditComponent
{...{ context, __unstableLayoutClassNames: layoutClassNames }}
/>
);
}
return <Placeholder layoutClassNames={layoutClassNames} />;
};
}
function enhancePostContentBlock() {
addFilter(
'blocks.registerBlockType',
'mailpoet-email-editor/change-post-content',
(settings: Block, name) => {
if (name === 'core/post-content') {
return {
...settings,
edit: PostContentEdit(settings.edit),
};
}
return settings;
},
);
}
export { enhancePostContentBlock };

View File

@ -1,18 +0,0 @@
import { unregisterFormatType } from '@wordpress/rich-text';
/**
* Disable Rich text formats we currently cannot support
* Note: This will remove its support for all blocks in the email editor e.g., p, h1,h2, etc
*/
function disableCertainRichTextFormats() {
// remove support for inline image - We can't use it
unregisterFormatType('core/image');
// remove support for Inline code - Not well formatted
unregisterFormatType('core/code');
// remove support for Language - Not supported for now
unregisterFormatType('core/language');
}
export { disableCertainRichTextFormats };

View File

@ -1,30 +0,0 @@
import { registerCoreBlocks } from '@wordpress/block-library';
import { enhanceColumnBlock } from './core/column';
import {
disableColumnsLayout,
deactivateStackOnMobile,
enhanceColumnsBlock,
} from './core/columns';
import { enhancePostContentBlock } from './core/post-content';
import { disableGroupVariations } from './core/group';
import { disableImageFilter, hideExpandOnClick } from './core/image';
import { disableCertainRichTextFormats } from './core/rich-text';
import { enhanceButtonBlock } from './core/button';
import { enhanceButtonsBlock } from './core/buttons';
import { alterSupportConfiguration } from './core/general-block-support';
export function initBlocks() {
deactivateStackOnMobile();
hideExpandOnClick();
disableImageFilter();
disableCertainRichTextFormats();
disableColumnsLayout();
disableGroupVariations();
enhanceButtonBlock();
enhanceButtonsBlock();
enhanceColumnBlock();
enhanceColumnsBlock();
enhancePostContentBlock();
alterSupportConfiguration();
registerCoreBlocks();
}

View File

@ -1,39 +0,0 @@
import { useDispatch, useSelect } from '@wordpress/data';
import { useEffect } from '@wordpress/element';
import { storeName } from '../../store';
/**
* This component is simplified version of the original one from @wordpress/editor package.
* The original component can be found here: https://github.com/WordPress/gutenberg/blob/46446b853d740c309c0675c7bf2ca4170a618c42/packages/editor/src/components/autosave-monitor/index.js
* The main reason for the own solution is that the original component needs to initialize the @wordpress/editor store.
* We could use the action `setEditedPost` from the editor package, but it is only in a newer version of the editor package.
*/
export function AutosaveMonitor() {
const { hasEdits, autosaveInterval } = useSelect(
(select) => ({
hasEdits: select(storeName).hasEdits(),
autosaveInterval: select(storeName).getAutosaveInterval(),
}),
[],
);
const { saveEditedEmail } = useDispatch(storeName);
useEffect(() => {
let autosaveTimer: NodeJS.Timeout | undefined;
if (hasEdits && autosaveInterval > 0) {
autosaveTimer = setTimeout(() => {
void saveEditedEmail();
}, autosaveInterval * 1000);
}
return () => {
if (autosaveTimer) {
clearTimeout(autosaveTimer);
}
};
}, [hasEdits, autosaveInterval, saveEditedEmail]);
return null;
}

View File

@ -1,105 +0,0 @@
/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';
import {
ErrorBoundary,
PostLockedModal,
// @ts-expect-error No types for this exist yet.
privateApis as editorPrivateApis,
} from '@wordpress/editor';
import { useMemo } from '@wordpress/element';
import { SlotFillProvider, Spinner } from '@wordpress/components';
import { store as coreStore } from '@wordpress/core-data';
import { storeName } from '../../store';
/**
* Internal dependencies
*/
import { Layout } from './layout';
import { unlock } from '../../../lock-unlock';
import { useNavigateToEntityRecord } from '../../hooks/use-navigate-to-entity-record';
const { ExperimentalEditorProvider } = unlock(editorPrivateApis);
export function InnerEditor({
postId: initialPostId,
postType: initialPostType,
settings,
initialEdits,
...props
}) {
const {
currentPost,
onNavigateToEntityRecord,
onNavigateToPreviousEntityRecord,
} = useNavigateToEntityRecord(
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
initialPostId,
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
initialPostType,
'post-only',
);
const { post, template } = useSelect(
(select) => {
const { getEntityRecord } = select(coreStore);
const { getEditedPostTemplate } = select(storeName);
const postObject = getEntityRecord(
'postType',
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
currentPost.postType,
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
currentPost.postId,
);
return {
template:
currentPost.postType !== 'wp_template'
? getEditedPostTemplate()
: null,
post: postObject,
};
},
[currentPost.postType, currentPost.postId],
);
const editorSettings = useMemo(
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
() => ({
...settings,
onNavigateToEntityRecord,
onNavigateToPreviousEntityRecord,
defaultRenderingMode: 'template-locked',
supportsTemplateMode: true,
}),
[settings, onNavigateToEntityRecord, onNavigateToPreviousEntityRecord],
);
if (!post || (currentPost.postType !== 'wp_template' && !template)) {
return (
<div className="spinner-container">
<Spinner style={{ width: '80px', height: '80px' }} />
</div>
);
}
return (
<SlotFillProvider>
<ExperimentalEditorProvider
settings={editorSettings}
post={post}
initialEdits={initialEdits}
useSubRegistry={false}
__unstableTemplate={template}
{...props}
>
{/* @ts-expect-error ErrorBoundary type is incorrect there is no onError */}
<ErrorBoundary>
<Layout />
<PostLockedModal />
</ErrorBoundary>
</ExperimentalEditorProvider>
</SlotFillProvider>
);
}

View File

@ -1,185 +0,0 @@
@import '~@wordpress/base-styles/colors';
#mailpoet-email-editor {
.editor-header__toolbar {
flex-grow: 1;
}
.editor-header__center {
flex-grow: 3;
}
}
// Specific styles for the component EmailTypeInfo
// Styles are based on the Block Card component from Gutenberg block editor
.mailpoet-email-sidebar__email-type-info {
.components-panel__row {
align-items: flex-start;
}
.mailpoet-email-type-info__icon {
flex: 0 0 24px;
margin-left: 0;
margin-right: 12px;
}
.mailpoet-email-type-info__content {
flex-grow: 1;
margin-bottom: 4px;
h2 {
font-size: 13px;
line-height: 24px;
margin: 0 0 4px;
}
span {
font-size: 13px;
}
}
}
.mailpoet-email-editor__settings-panel {
.mailpoet-settings-panel__subject .components-base-control__label {
width: 100%;
.components-external-link {
float: right;
}
}
.mailpoet-settings-panel__help {
margin-bottom: 20px;
.components-text {
color: #757575;
}
}
.mailpoet-settings-panel__preview-text .components-base-control__label {
width: 100%;
}
.mailpoet-settings-panel__preview-text-length {
color: $black;
display: inline-block;
float: right;
padding: 3px;
}
.mailpoet-settings-panel__preview-text-length-warning {
color: $alert-yellow;
}
.mailpoet-settings-panel__preview-text-length-error {
color: $alert-red;
}
}
.edit-post-visual-editor {
line-height: 1.4; /* Recommended line-height that is also used in the email editor */
margin: 0;
min-height: 100%;
padding: 0;
-webkit-text-size-adjust: 100%; /* From MJMJ - Automatic test adjustment on mobile max to 100% */
-ms-text-size-adjust: 100%; /* From MJMJ - Automatic test adjustment on mobile max to 100% */
word-spacing: normal;
}
.visual-editor__email_layout_wrapper {
height: 100%;
margin: 0 auto;
padding: 0;
width: 100%;
}
.visual-editor__email_content_wrapper {
display: flex;
height: 100%;
width: 100%;
> div {
width: 100%;
}
// Set default padding-left to have consistent default look in editor and in email
// This also overrides the default values in browsers for padding-inline-start
ul,
ol,
ul.has-background,
ol.has-background {
padding-left: 40px;
}
// Override default button border radius which is set in core to 9999px
.wp-block-button__link {
border-radius: 0;
}
.is-mobile-preview {
.wp-block-columns {
display: flex;
flex-direction: column;
.wp-block-column {
box-sizing: border-box;
// override flex-basis set in style attribute to fix the height of the column in mobile preview. Blocks overriding is as a part of style.css in blocks-library
flex-basis: auto !important;
}
}
}
// Fix for mobile preview height
&.is-mobile-preview {
> div {
display: block !important;
}
.editor-styles-wrapper {
height: auto !important;
}
}
}
.has-global-padding .wp-block-post-content > .alignfull {
margin-left: -20px;
margin-right: -20px;
}
// For the WYSIWYG experience we don't want to display any margins between blocks in the editor
.wp-block {
clear: both; // for ensuring that floated elements (images) are cleared
}
// Resetting the margin for images in the editor to avoid unexpected spacing
.editor-styles-wrapper .is-layout-constrained .wp-block-image {
figcaption {
margin: 0;
}
&.alignleft,
&.alignright {
margin-inline-end: 0;
margin-inline-start: 0;
text-align: center;
}
&.aligncenter {
margin-left: auto;
margin-right: auto;
}
}
.editor-styles-wrapper {
.wp-block-columns:not(.is-not-stacked-on-mobile)
> .wp-block-column[style*='flex-basis'] {
box-sizing: border-box;
}
}
// Content does not need margin. The rendered template does not add margins to match.
.editor-styles-wrapper .wp-block-post-content {
margin: 0;
}
// Hide the advanced settings in the sidebar. This panel is not used in the email editor at this moment.
.block-editor-block-inspector__advanced {
display: none;
}

View File

@ -1,151 +0,0 @@
import {
// @ts-expect-error No types for this exist yet.
__experimentalUseResizeCanvas as useResizeCanvas,
BlockSelectionClearer,
} from '@wordpress/block-editor';
import {
UnsavedChangesWarning,
// @ts-expect-error No types for this exist yet.
privateApis as editorPrivateApis,
store as editorStore,
} from '@wordpress/editor';
import { uploadMedia } from '@wordpress/media-utils';
import classnames from 'classnames';
import { useSelect, useDispatch } from '@wordpress/data';
import {
ComplementaryArea,
FullscreenMode,
InterfaceSkeleton,
} from '@wordpress/interface';
import './index.scss';
import { store as coreStore } from '@wordpress/core-data';
import { storeName } from '../../store';
import { useEmailCss } from '../../hooks';
import { AutosaveMonitor } from '../autosave';
import { BlockCompatibilityWarnings, Sidebar } from '../sidebar';
import { Header } from '../header';
import { ListviewSidebar } from '../listview-sidebar/listview-sidebar';
import { InserterSidebar } from '../inserter-sidebar/inserter-sidebar';
import { EditorNotices, SentEmailNotice } from '../notices';
import { StylesSidebar } from '../styles-sidebar';
import { unlock } from '../../../lock-unlock';
import { TemplateSelection } from '../template-select';
const { EditorCanvas } = unlock(editorPrivateApis);
export function Layout() {
const {
isFullscreenActive,
isSidebarOpened,
initialSettings,
previewDeviceType,
isInserterSidebarOpened,
isListviewSidebarOpened,
canUserEditMedia,
hasFixedToolbar,
focusMode,
styles,
isEditingTemplate,
} = useSelect(
(select) => ({
isFullscreenActive: select(storeName).isFeatureActive('fullscreenMode'),
isSidebarOpened: select(storeName).isSidebarOpened(),
isInserterSidebarOpened: select(storeName).isInserterSidebarOpened(),
isListviewSidebarOpened: select(storeName).isListviewSidebarOpened(),
initialSettings: select(storeName).getInitialEditorSettings(),
previewDeviceType: select(storeName).getPreviewState().deviceType,
canUserEditMedia: select(coreStore).canUser('create', 'media'),
hasFixedToolbar: select(storeName).isFeatureActive('fixedToolbar'),
focusMode: select(storeName).isFeatureActive('focusMode'),
styles: select(storeName).getStyles(),
isEditingTemplate:
select(editorStore).getCurrentPostType() === 'wp_template',
}),
[],
);
const { toggleInserterSidebar } = useDispatch(storeName);
const [emailCss] = useEmailCss();
const className = classnames('edit-post-layout', {
'is-sidebar-opened': isSidebarOpened,
});
const contentWrapperStyles = useResizeCanvas(previewDeviceType);
if (isEditingTemplate) {
contentWrapperStyles.height = '100%';
}
// Styles for the canvas. Based on template-canvas.php, this equates to the body element.
const canvasStyles = {
background:
previewDeviceType === 'Desktop' ? styles.color.background : 'transparent',
fontFamily: styles.typography.fontFamily,
transition: 'all 0.3s ease 0s',
};
const settings = {
...initialSettings,
mediaUpload: canUserEditMedia ? uploadMedia : null,
hasFixedToolbar,
focusMode,
};
return (
<>
<FullscreenMode isActive={isFullscreenActive} />
<UnsavedChangesWarning />
<AutosaveMonitor />
<SentEmailNotice />
<Sidebar />
<StylesSidebar />
<TemplateSelection />
<InterfaceSkeleton
className={className}
header={<Header />}
editorNotices={<EditorNotices />}
content={
<>
<EditorNotices />
<BlockSelectionClearer
className="edit-post-visual-editor"
style={canvasStyles}
onClick={() => {
// Clear inserter sidebar when canvas is clicked.
if (isInserterSidebarOpened) {
void toggleInserterSidebar();
}
}}
>
<div
className={classnames('visual-editor__email_content_wrapper', {
'is-mobile-preview': previewDeviceType === 'Mobile',
'is-desktop-preview': previewDeviceType === 'Desktop',
})}
style={contentWrapperStyles}
>
<EditorCanvas
disableIframe={false}
styles={[...settings.styles, ...emailCss]}
autoFocus
className="has-global-padding"
renderAppender={false} // With false the appender is rendered in the template mode
/>
</div>
</BlockSelectionClearer>
</>
}
sidebar={<ComplementaryArea.Slot scope={storeName} />}
secondarySidebar={
(isInserterSidebarOpened && <InserterSidebar />) ||
(isListviewSidebarOpened && <ListviewSidebar />)
}
/>
{/* Rendering Warning component here ensures that the warning is displayed under the border configuration. */}
<BlockCompatibilityWarnings />
</>
);
}

View File

@ -1,85 +0,0 @@
import { useRef } from '@wordpress/element';
import {
Button,
Dropdown,
VisuallyHidden,
__experimentalText as Text,
TextControl,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { chevronDown } from '@wordpress/icons';
import { useSelect } from '@wordpress/data';
import { useEntityProp } from '@wordpress/core-data';
import { storeName } from '../../store';
// @see https://github.com/WordPress/gutenberg/blob/5e0ffdbc36cb2e967dfa6a6b812a10a2e56a598f/packages/edit-post/src/components/header/document-actions/index.js
export function CampaignName() {
const { showIconLabels } = useSelect(
(select) => ({
showIconLabels: select(storeName).isFeatureActive('showIconLabels'),
postId: select(storeName).getEmailPostId(),
}),
[],
);
const [emailTitle = '', setTitle] = useEntityProp(
'postType',
'mailpoet_email',
'title',
);
const titleRef = useRef(null);
return (
<div ref={titleRef} className="mailpoet-email-editor-campaign-name">
<Dropdown
popoverProps={{
placement: 'bottom',
anchor: titleRef.current,
}}
contentClassName="mailpoet-email-editor-campaign-name__dropdown"
renderToggle={({ isOpen, onToggle }) => (
<>
<Button
onClick={onToggle}
className="mailpoet-email-campaign-name__link"
>
<Text size="body" as="h1">
<VisuallyHidden as="span">
{__('Editing email:', 'mailpoet')}
</VisuallyHidden>
{emailTitle}
</Text>
</Button>
<Button
className="mailpoet-email-campaign-name__toggle"
icon={chevronDown}
aria-expanded={isOpen}
aria-haspopup="true"
onClick={onToggle}
label={__('Change campaign name', 'mailpoet')}
>
{showIconLabels && __('Rename', 'mailpoet')}
</Button>
</>
)}
renderContent={() => (
<div className="mailpoet-email-editor-email-title-edit">
<TextControl
label={__('Campaign name', 'mailpoet')}
value={emailTitle}
onChange={(newTitle) => {
setTitle(newTitle);
}}
name="campaign_name"
help={__(
`Name your email campaign to indicate its purpose. This would only be visible to you and not shown to your subscribers.`,
'mailpoet',
)}
/>
</div>
)}
/>
</div>
);
}

View File

@ -1,192 +0,0 @@
import { useRef, useState } from '@wordpress/element';
import { PinnedItems } from '@wordpress/interface';
import { Button, ToolbarItem as WpToolbarItem } from '@wordpress/components';
import {
NavigableToolbar,
BlockToolbar as WPBlockToolbar,
store as blockEditorStore,
} from '@wordpress/block-editor';
import { useSelect, useDispatch } from '@wordpress/data';
import { store as coreDataStore } from '@wordpress/core-data';
// @ts-expect-error DocumentBar types are not available
import { DocumentBar, store as editorStore } from '@wordpress/editor';
import { store as preferencesStore } from '@wordpress/preferences';
import { __ } from '@wordpress/i18n';
import { plus, listView, undo, redo, next, previous } from '@wordpress/icons';
import classnames from 'classnames';
import { storeName } from '../../store';
import { MoreMenu } from './more-menu';
import { PreviewDropdown } from '../preview';
import { SaveButton } from './save-button';
import { CampaignName } from './campaign-name';
import { SendButton } from './send-button';
import { unlock } from '../../../lock-unlock';
// Build type for ToolbarItem contains only "as" and "children" properties but it takes all props from
// component passed to "as" property (in this case Button). So as fix for TS errors we need to pass all props from Button to ToolbarItem.
// We should be able to remove this fix when ToolbarItem will be fixed in Gutenberg.
const ToolbarItem = WpToolbarItem as React.ForwardRefExoticComponent<
React.ComponentProps<typeof WpToolbarItem> &
React.ComponentProps<typeof Button>
>;
// Definition of BlockToolbar in currently installed Gutenberg packages (wp-6.4) is missing hideDragHandle prop
// After updating to newer version of Gutenberg we should be able to remove this fix
const BlockToolbar = WPBlockToolbar as React.FC<
React.ComponentProps<typeof WPBlockToolbar> & {
hideDragHandle?: boolean;
}
>;
export function Header() {
const inserterButton = useRef();
const listviewButton = useRef();
const undoButton = useRef();
const redoButton = useRef();
const [isBlockToolsCollapsed, setIsBlockToolsCollapsed] = useState(false);
const { toggleInserterSidebar, toggleListviewSidebar } =
useDispatch(storeName);
const { undo: undoAction, redo: redoAction } = useDispatch(coreDataStore);
const {
isInserterSidebarOpened,
isListviewSidebarOpened,
isFixedToolbarActive,
isBlockSelected,
hasUndo,
hasRedo,
hasDocumentNavigationHistory,
} = useSelect((select) => {
// eslint-disable-next-line @typescript-eslint/naming-convention
const { getEditorSettings: _getEditorSettings } = unlock(
select(editorStore),
);
const editorSettings = _getEditorSettings();
return {
isInserterSidebarOpened: select(storeName).isInserterSidebarOpened(),
isListviewSidebarOpened: select(storeName).isListviewSidebarOpened(),
isFixedToolbarActive: select(preferencesStore).get(
'core',
'fixedToolbar',
),
isBlockSelected: !!select(blockEditorStore).getBlockSelectionStart(),
hasUndo: select(coreDataStore).hasUndo(),
hasRedo: select(coreDataStore).hasRedo(),
hasDocumentNavigationHistory:
!!editorSettings.onNavigateToPreviousEntityRecord,
};
}, []);
const preventDefault = (event) => {
event.preventDefault();
};
const shortLabelInserter = !isInserterSidebarOpened
? __('Add', 'mailpoet')
: __('Close', 'mailpoet');
return (
<div className="editor-header edit-post-header">
<div className="editor-header__toolbar edit-post-header__toolbar">
<NavigableToolbar
className="editor-header__toolbar edit-post-header-toolbar is-unstyled editor-document-tools"
aria-label={__('Email document tools', 'mailpoet')}
>
<div className="editor-document-tools__left">
<ToolbarItem
ref={inserterButton}
as={Button}
className="editor-header-toolbar__inserter-toggle edit-post-header-toolbar__inserter-toggle"
variant="primary"
isPressed={isInserterSidebarOpened}
onMouseDown={preventDefault}
onClick={toggleInserterSidebar}
disabled={false}
icon={plus}
label={shortLabelInserter}
showTooltip
aria-expanded={isInserterSidebarOpened}
/>
<ToolbarItem
ref={undoButton}
as={Button}
className="editor-history__undo"
isPressed={false}
onMouseDown={preventDefault}
onClick={undoAction}
disabled={!hasUndo}
icon={undo}
label={__('Undo', 'mailpoet')}
showTooltip
/>
<ToolbarItem
ref={redoButton}
as={Button}
className="editor-history__redo"
isPressed={false}
onMouseDown={preventDefault}
onClick={redoAction}
disabled={!hasRedo}
icon={redo}
label={__('Redo', 'mailpoet')}
showTooltip
/>
<ToolbarItem
ref={listviewButton}
as={Button}
className="editor-header-toolbar__document-overview-toggle edit-post-header-toolbar__document-overview-toggle"
isPressed={isListviewSidebarOpened}
onMouseDown={preventDefault}
onClick={toggleListviewSidebar}
disabled={false}
icon={listView}
label={__('List view', 'mailpoet')}
showTooltip
aria-expanded={isInserterSidebarOpened}
/>
</div>
</NavigableToolbar>
{isFixedToolbarActive && isBlockSelected && (
<>
<div
className={classnames('selected-block-tools-wrapper', {
'is-collapsed': isBlockToolsCollapsed,
})}
>
<BlockToolbar hideDragHandle />
</div>
<Button
className="editor-header__block-tools-toggle edit-post-header__block-tools-toggle"
icon={isBlockToolsCollapsed ? next : previous}
onClick={() => {
setIsBlockToolsCollapsed((collapsed) => !collapsed);
}}
label={
isBlockToolsCollapsed
? __('Show block tools', 'mailpoet')
: __('Hide block tools', 'mailpoet')
}
/>
</>
)}
{(!isFixedToolbarActive ||
!isBlockSelected ||
isBlockToolsCollapsed) && (
<div className="editor-header__center edit-post-header__center">
{hasDocumentNavigationHistory ? <DocumentBar /> : <CampaignName />}
</div>
)}
</div>
<div className="editor-header__settings edit-post-header__settings">
<SaveButton />
<PreviewDropdown />
<SendButton />
<PinnedItems.Slot scope={storeName} />
<MoreMenu />
</div>
</div>
);
}

View File

@ -1,41 +0,0 @@
// Document actions - Component in header for displaying email/campaign title edit popup
.mailpoet-email-editor-campaign-name {
align-items: center;
display: flex;
flex-direction: row;
justify-content: center;
min-width: 0;
.components-dropdown {
display: inline-flex;
}
.components-button {
min-width: 0;
padding: 0;
}
.mailpoet-email-campaign-name__link {
display: inline-flex;
height: fit-content;
margin-right: 10px;
margin-top: 10px;
}
}
// Document actions - Popup for editing email/campaign title
.mailpoet-email-editor-campaign-name__dropdown {
.components-popover__content {
min-width: 280px;
padding: 0;
}
.mailpoet-email-editor-email-title-edit {
padding: 16px;
}
}
.mailpoet-email-editor-save-button__dropdown {
.components-popover__content {
min-width: 280px;
}
}

View File

@ -1,113 +0,0 @@
import { MenuGroup, MenuItem, DropdownMenu } from '@wordpress/components';
import { useState } from '@wordpress/element';
import { displayShortcut } from '@wordpress/keycodes';
import { moreVertical } from '@wordpress/icons';
import { useEntityProp } from '@wordpress/core-data';
import { __, _x } from '@wordpress/i18n';
import { PreferenceToggleMenuItem } from '@wordpress/preferences';
import { useSelect, useDispatch } from '@wordpress/data';
import { storeName } from '../../store';
import { TrashModal } from './trash-modal';
// See:
// https://github.com/WordPress/gutenberg/blob/9601a33e30ba41bac98579c8d822af63dd961488/packages/edit-post/src/components/header/more-menu/index.js
// https://github.com/WordPress/gutenberg/blob/0ee78b1bbe9c6f3e6df99f3b967132fa12bef77d/packages/edit-site/src/components/header/more-menu/index.js
export function MoreMenu(): JSX.Element {
const [showTrashModal, setShowTrashModal] = useState(false);
const { urls, postId } = useSelect(
(select) => ({
urls: select(storeName).getUrls(),
postId: select(storeName).getEmailPostId(),
}),
[],
);
const [status, setStatus] = useEntityProp(
'postType',
'mailpoet_email',
'status',
);
const { saveEditedEmail, updateEmailMailPoetProperty } =
useDispatch(storeName);
const goToListings = () => {
window.location.href = urls.listings;
};
return (
<>
<DropdownMenu
className="edit-site-more-menu"
popoverProps={{
className: 'edit-site-more-menu__content',
}}
icon={moreVertical}
label={__('More', 'mailpoet')}
>
{() => (
<>
<MenuGroup label={_x('View', 'noun', 'mailpoet')}>
<PreferenceToggleMenuItem
scope={storeName}
name="fixedToolbar"
label={__('Top toolbar', 'mailpoet')}
info={__(
'Access all block and document tools in a single place',
'mailpoet',
)}
messageActivated={__('Top toolbar activated', 'mailpoet')}
messageDeactivated={__('Top toolbar deactivated', 'mailpoet')}
/>
<PreferenceToggleMenuItem
scope={storeName}
name="focusMode"
label={__('Spotlight mode', 'mailpoet')}
info={__('Focus at one block at a time', 'mailpoet')}
messageActivated={__('Spotlight mode activated', 'mailpoet')}
messageDeactivated={__(
'Spotlight mode deactivated',
'mailpoet',
)}
/>
<PreferenceToggleMenuItem
scope={storeName}
name="fullscreenMode"
label={__('Fullscreen mode', 'mailpoet')}
info={__('Work without distraction', 'mailpoet')}
messageActivated={__('Fullscreen mode activated', 'mailpoet')}
messageDeactivated={__(
'Fullscreen mode deactivated',
'mailpoet',
)}
shortcut={displayShortcut.secondary('f')}
/>
</MenuGroup>
<MenuGroup>
{status === 'trash' ? (
<MenuItem
onClick={async () => {
await setStatus('draft');
await updateEmailMailPoetProperty('deleted_at', '');
await saveEditedEmail();
}}
>
{__('Restore from trash', 'mailpoet')}
</MenuItem>
) : (
<MenuItem onClick={() => setShowTrashModal(true)} isDestructive>
{__('Move to trash', 'mailpoet')}
</MenuItem>
)}
</MenuGroup>
</>
)}
</DropdownMenu>
{showTrashModal && (
<TrashModal
onClose={() => setShowTrashModal(false)}
onRemove={goToListings}
postId={postId}
/>
)}
</>
);
}

View File

@ -1,71 +0,0 @@
import { useRef } from '@wordpress/element';
import { Button, Dropdown } from '@wordpress/components';
import {
// @ts-expect-error No types available for useEntitiesSavedStatesIsDirty
useEntitiesSavedStatesIsDirty,
// @ts-expect-error Our current version of packages doesn't have EntitiesSavedStates export
EntitiesSavedStates,
} from '@wordpress/editor';
import { __ } from '@wordpress/i18n';
import { useDispatch, useSelect } from '@wordpress/data';
import { check, cloud, Icon } from '@wordpress/icons';
import { storeName } from '../../store';
export function SaveButton() {
const { saveEditedEmail } = useDispatch(storeName);
const { dirtyEntityRecords } = useEntitiesSavedStatesIsDirty();
const { hasEdits, isEmpty, isSaving } = useSelect(
(select) => ({
hasEdits: select(storeName).hasEdits(),
isEmpty: select(storeName).isEmpty(),
isSaving: select(storeName).isSaving(),
}),
[],
);
const buttonRef = useRef(null);
const hasNonEmailEdits = dirtyEntityRecords.some(
(entity) => entity.name !== 'mailpoet_email',
);
const isSaved = !isEmpty && !isSaving && !hasEdits;
const isDisabled = isEmpty || isSaving || isSaved;
let label = __('Save Draft', 'mailpoet');
if (isSaved) {
label = __('Saved', 'mailpoet');
} else if (isSaving) {
label = __('Saving', 'mailpoet');
}
return hasNonEmailEdits ? (
<div ref={buttonRef}>
<Dropdown
popoverProps={{
placement: 'bottom',
anchor: buttonRef.current,
}}
contentClassName="mailpoet-email-editor-save-button__dropdown"
renderToggle={({ onToggle }) => (
<Button onClick={onToggle} variant="tertiary">
{hasEdits
? __('Save email & template', 'mailpoet')
: __('Save template', 'mailpoet')}
</Button>
)}
renderContent={({ onToggle }) => (
<EntitiesSavedStates close={onToggle} />
)}
/>
</div>
) : (
<Button variant="tertiary" disabled={isDisabled} onClick={saveEditedEmail}>
{isSaving && <Icon icon={cloud} />}
{isSaved && <Icon icon={check} />}
{label}
</Button>
);
}

View File

@ -1,50 +0,0 @@
import { __ } from '@wordpress/i18n';
import { Button } from '@wordpress/components';
import {
store as editorStore,
// @ts-expect-error No types available for useEntitiesSavedStatesIsDirty
useEntitiesSavedStatesIsDirty,
} from '@wordpress/editor';
import { useEntityProp } from '@wordpress/core-data';
import { MailPoetEmailData, storeName } from 'email-editor/engine/store';
import { useSelect } from '@wordpress/data';
import { useContentValidation } from 'email-editor/engine/hooks';
export function SendButton() {
const [mailpoetEmail] = useEntityProp(
'postType',
'mailpoet_email',
'mailpoet_data',
);
const { isDirty } = useEntitiesSavedStatesIsDirty();
const { validateContent, isValid } = useContentValidation();
const { hasEmptyContent, isEmailSent, isEditingTemplate } = useSelect(
(select) => ({
hasEmptyContent: select(storeName).hasEmptyContent(),
isEmailSent: select(storeName).isEmailSent(),
isEditingTemplate:
select(editorStore).getCurrentPostType() === 'wp_template',
}),
[],
);
const isDisabled =
isEditingTemplate || hasEmptyContent || isEmailSent || isValid || isDirty;
const mailpoetEmailData: MailPoetEmailData = mailpoetEmail;
return (
<Button
variant="primary"
onClick={() => {
if (validateContent()) {
window.location.href = `admin.php?page=mailpoet-newsletters#/send/${mailpoetEmailData.id}`;
}
}}
disabled={isDisabled}
>
{__('Send', 'mailpoet')}
</Button>
);
}

View File

@ -1,78 +0,0 @@
import { __ } from '@wordpress/i18n';
import { Button, Modal } from '@wordpress/components';
import { useDispatch, useSelect } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';
import { store as noticesStore } from '@wordpress/notices';
export function TrashModal({
onClose,
onRemove,
postId,
}: {
onClose: () => void;
onRemove: () => void;
postId: number;
}) {
const { getLastEntityDeleteError } = useSelect(coreStore);
const { deleteEntityRecord } = useDispatch(coreStore);
const { createErrorNotice } = useDispatch(noticesStore);
const closeCallback = () => {
onClose();
};
const trashCallback = async () => {
const success = await deleteEntityRecord(
'postType',
'mailpoet_email',
postId as unknown as string,
{},
{ throwOnError: false },
);
if (success) {
onRemove();
} else {
const lastError = getLastEntityDeleteError(
'postType',
'mailpoet_email',
postId,
);
// Already deleted.
if (lastError?.code === 410) {
onRemove();
} else {
const errorMessage = lastError?.message
? (lastError.message as string)
: __(
'An error occurred while moving the email to the trash.',
'mailpoet',
);
await createErrorNotice(errorMessage, {
type: 'snackbar',
isDismissible: true,
context: 'email-editor',
});
}
}
};
return (
<Modal
className="mailpoet-move-to-trash-modal"
title={__('Move to trash', 'mailpoet')}
onRequestClose={closeCallback}
focusOnMount="firstContentElement"
>
<p>
{__('Are you sure you want to move this email to trash?', 'mailpoet')}
</p>
<div className="mailpoet-send-preview-modal-footer">
<Button variant="tertiary" onClick={closeCallback}>
{__('Cancel', 'mailpoet')}
</Button>
<Button variant="primary" onClick={trashCallback}>
{__('Move to trash', 'mailpoet')}
</Button>
</div>
</Modal>
);
}
export default TrashModal;

View File

@ -1,31 +0,0 @@
import {
__experimentalLibrary as Library,
store as blockEditorStore,
} from '@wordpress/block-editor';
import { useSelect } from '@wordpress/data';
import { store as editorStore } from '@wordpress/editor';
export function InserterSidebar() {
const { postContentId, isEditingEmailContent } = useSelect((select) => {
const blocks = select(blockEditorStore).getBlocks();
return {
postContentId: blocks.find((block) => block.name === 'core/post-content')
?.clientId,
isEditingEmailContent:
select(editorStore).getCurrentPostType() !== 'wp_template',
};
});
return (
<div className="edit-post-editor__inserter-panel">
<div className="edit-post-editor__inserter-panel-content">
<Library
showMostUsedBlocks
showInserterHelpPanel={false}
// In the email content mode we insert primarily into the post content block.
rootClientId={isEditingEmailContent ? postContentId : null}
/>
</div>
</div>
);
}

View File

@ -1,81 +0,0 @@
import { useSelect, useDispatch } from '@wordpress/data';
import { useEffect } from '@wordpress/element';
import {
useShortcut,
store as keyboardShortcutsStore,
} from '@wordpress/keyboard-shortcuts';
import { __ } from '@wordpress/i18n';
import { storeName } from '../../store';
// See:
// https://github.com/WordPress/gutenberg/blob/9601a33e30ba41bac98579c8d822af63dd961488/packages/edit-post/src/components/keyboard-shortcuts/index.js
// https://github.com/WordPress/gutenberg/blob/0ee78b1bbe9c6f3e6df99f3b967132fa12bef77d/packages/edit-site/src/components/keyboard-shortcuts/index.js
export function KeyboardShortcuts(): null {
const { isSidebarOpened, hasEdits, isSaving } = useSelect((select) => ({
isSidebarOpened: select(storeName).isSidebarOpened(),
isSaving: select(storeName).isSaving(),
hasEdits: select(storeName).hasEdits(),
}));
const { openSidebar, closeSidebar, saveEditedEmail, toggleFeature } =
useDispatch(storeName);
const { registerShortcut } = useDispatch(keyboardShortcutsStore);
useEffect(() => {
void registerShortcut({
name: 'mailpoet/email-editor/toggle-fullscreen',
category: 'global',
description: __('Toggle fullscreen mode.', 'mailpoet'),
keyCombination: {
modifier: 'secondary',
character: 'f',
},
});
void registerShortcut({
name: 'mailpoet/email-editor/toggle-sidebar',
category: 'global',
description: __('Show or hide the settings sidebar.', 'mailpoet'),
keyCombination: {
modifier: 'primaryShift',
character: ',',
},
});
void registerShortcut({
name: 'mailpoet/email-editor/save',
category: 'global',
description: __('Save your changes.', 'mailpoet'),
keyCombination: {
modifier: 'primary',
character: 's',
},
});
}, [registerShortcut]);
useShortcut('mailpoet/email-editor/toggle-fullscreen', () => {
void toggleFeature('fullscreenMode');
});
useShortcut('mailpoet/email-editor/toggle-sidebar', (event) => {
event.preventDefault();
if (isSidebarOpened) {
void closeSidebar();
} else {
void openSidebar();
}
});
useShortcut('mailpoet/email-editor/save', (event) => {
event.preventDefault();
if (!hasEdits || isSaving) {
return;
}
void saveEditedEmail();
});
return null;
}

View File

@ -1,13 +0,0 @@
import { __experimentalListView as ListView } from '@wordpress/block-editor';
export function ListviewSidebar() {
return (
<div className="edit-post-editor__inserter-panel edit-post-editor__document-overview-panel">
<div className="edit-post-editor__list-view-panel-content">
<div className="edit-post-editor__list-view-container">
<ListView />
</div>
</div>
</div>
);
}

View File

@ -1,19 +0,0 @@
.components-notice.mailpoet-email-editor-validation-errors {
margin: 0;
ul {
list-style: disc outside;
margin: 0 0 0 20px;
}
li {
margin: 8px 0;
padding: 0;
}
li:last-child {
margin-bottom: 0;
}
button.components-button.is-link {
color: #1e1e1e;
margin: 0 4px;
}
}

View File

@ -1,43 +0,0 @@
import { NoticeList } from '@wordpress/components';
import { useSelect, useDispatch } from '@wordpress/data';
import { store as noticesStore } from '@wordpress/notices';
import { ValidationNotices } from './validation-notices';
import { EditorSnackbars } from './snackbars';
// See: https://github.com/WordPress/gutenberg/blob/5be0ec4153c3adf9f0f2513239f4f7a358ba7948/packages/editor/src/components/editor-notices/index.js
export function EditorNotices() {
const { notices } = useSelect(
(select) => ({
notices: select(noticesStore).getNotices('email-editor'),
}),
[],
);
const { removeNotice } = useDispatch(noticesStore);
const dismissibleNotices = notices.filter(
({ isDismissible, type }) => isDismissible && type === 'default',
);
const nonDismissibleNotices = notices.filter(
({ isDismissible, type }) => !isDismissible && type === 'default',
);
return (
<>
<NoticeList
notices={nonDismissibleNotices}
className="components-editor-notices__pinned"
/>
<NoticeList
notices={dismissibleNotices}
className="components-editor-notices__dismissible"
onRemove={(id) => removeNotice(id, 'email-editor')}
/>
<ValidationNotices />
<EditorSnackbars context="global" />
<EditorSnackbars context="email-editor" />
</>
);
}

View File

@ -1,34 +0,0 @@
import { dispatch, useSelect } from '@wordpress/data';
import { useEffect } from '@wordpress/element';
import { store as noticesStore } from '@wordpress/notices';
import { __ } from '@wordpress/i18n';
import { storeName } from '../../store';
export function SentEmailNotice() {
const { isEmailSent } = useSelect(
(select) => ({
isEmailSent: select(storeName).isEmailSent(),
}),
[],
);
useEffect(() => {
if (isEmailSent) {
void dispatch(noticesStore).createNotice(
'warning',
__(
'This email has already been sent. It can be edited, but not sent again. Duplicate this email if you want to send it again.',
'mailpoet',
),
{
id: 'email-sent',
isDismissible: false,
context: 'email-editor',
},
);
}
}, [isEmailSent]);
return null;
}

View File

@ -1,26 +0,0 @@
import { SnackbarList } from '@wordpress/components';
import { useSelect, useDispatch } from '@wordpress/data';
import { store as noticesStore } from '@wordpress/notices';
// See: https://github.com/WordPress/gutenberg/blob/2788a9cf8b8149be3ee52dd15ce91fa55815f36a/packages/editor/src/components/editor-snackbars/index.js
export function EditorSnackbars({ context = 'email-editor' }) {
const { notices } = useSelect(
(select) => ({
notices: select(noticesStore).getNotices(context),
}),
[],
);
const { removeNotice } = useDispatch(noticesStore);
const snackbarNotices = notices.filter(({ type }) => type === 'snackbar');
return (
<SnackbarList
notices={snackbarNotices}
className="components-editor-notices__snackbar"
onRemove={(id) => removeNotice(id, context)}
/>
);
}

View File

@ -1,37 +0,0 @@
import { __ } from '@wordpress/i18n';
import { Notice, Button } from '@wordpress/components';
import { useValidationNotices } from 'email-editor/engine/hooks';
export function ValidationNotices() {
const { notices } = useValidationNotices();
if (notices.length === 0) {
return null;
}
return (
<Notice
status="error"
className="mailpoet-email-editor-validation-errors components-editor-notices__pinned"
isDismissible={false}
>
<>
<strong>{__('Fix errors to continue:', 'mailpoet')}</strong>
<ul>
{notices.map(({ id, content, actions }) => (
<li key={id}>
{content}
{actions.length > 0
? actions.map(({ label, onClick }) => (
<Button key={label} onClick={onClick} variant="link">
{label}
</Button>
))
: null}
</li>
))}
</ul>
</>
</Notice>
);
}

View File

@ -1,28 +0,0 @@
.components-modal__frame.mailpoet-send-preview-email {
max-width: 456px;
}
.mailpoet-send-preview-modal-footer {
display: flex;
gap: 12px;
justify-content: flex-end;
padding-top: 16px;
}
.mailpoet-send-preview-modal-notice-error {
background-color: #fcf0f1;
gap: 12px;
padding: 12px 16px;
ul {
list-style: disc;
margin: 0;
padding: 5px 0 0 20px;
}
}
.mailpoet-send-preview-modal-notice-success {
align-items: center;
display: flex;
padding-top: 2px;
}

View File

@ -1,100 +0,0 @@
import {
MenuGroup,
MenuItem,
Button,
DropdownMenu,
} from '@wordpress/components';
import { useEntityProp } from '@wordpress/core-data';
import { useDispatch, useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { Icon, external, check, mobile, desktop } from '@wordpress/icons';
import { SendPreviewEmail } from './send-preview-email';
import { storeName } from '../../store';
export function PreviewDropdown() {
const [mailpoetEmailData] = useEntityProp(
'postType',
'mailpoet_email',
'mailpoet_data',
);
const previewDeviceType = useSelect((select) => {
const { deviceType } = select(storeName).getPreviewState();
return deviceType;
}, []);
const { changePreviewDeviceType, togglePreviewModal } =
useDispatch(storeName);
const newsletterPreviewUrl: string = mailpoetEmailData?.preview_url || '';
const changeDeviceType = (newDeviceType: string) => {
void changePreviewDeviceType(newDeviceType);
};
const openInNewTab = (url: string) => {
window.open(url, '_blank', 'noreferrer');
};
const deviceIcons = {
mobile,
desktop,
};
return (
<>
<DropdownMenu
className="mailpoet-preview-dropdown"
label={__('Preview', 'mailpoet')}
icon={deviceIcons[previewDeviceType.toLowerCase()]}
>
{({ onClose }) => (
<>
<MenuGroup>
<MenuItem
className="block-editor-post-preview__button-resize"
onClick={() => changeDeviceType('Desktop')}
icon={previewDeviceType === 'Desktop' && check}
>
{__('Desktop', 'mailpoet')}
</MenuItem>
<MenuItem
className="block-editor-post-preview__button-resize"
onClick={() => changeDeviceType('Mobile')}
icon={previewDeviceType === 'Mobile' && check}
>
{__('Mobile', 'mailpoet')}
</MenuItem>
</MenuGroup>
<MenuGroup>
<MenuItem
className="block-editor-post-preview__button-resize"
onClick={() => {
void togglePreviewModal(true);
onClose();
}}
>
{__('Send a test email', 'mailpoet')}
</MenuItem>
</MenuGroup>
{newsletterPreviewUrl ? (
<MenuGroup>
<div className="edit-post-header-preview__grouping-external">
<Button
className="edit-post-header-preview__button-external components-menu-item__button"
onClick={() => {
openInNewTab(newsletterPreviewUrl);
}}
>
{__('Preview in new tab', 'mailpoet')}
<Icon icon={external} />
</Button>
</div>
</MenuGroup>
) : null}
</>
)}
</DropdownMenu>
<SendPreviewEmail />
</>
);
}

View File

@ -1,177 +0,0 @@
import { Button, Modal, TextControl } from '@wordpress/components';
import { useDispatch, useSelect } from '@wordpress/data';
import { check, Icon } from '@wordpress/icons';
import { __ } from '@wordpress/i18n';
import {
useEffect,
useRef,
createInterpolateElement,
} from '@wordpress/element';
import { ENTER } from '@wordpress/keycodes';
import { isEmail } from '@wordpress/url';
import { useEntityProp } from '@wordpress/core-data';
import {
MailPoetEmailData,
SendingPreviewStatus,
storeName,
} from '../../store';
export function SendPreviewEmail() {
const sendToRef = useRef(null);
const {
requestSendingNewsletterPreview,
togglePreviewModal,
updateSendPreviewEmail,
} = useDispatch(storeName);
const {
toEmail: previewToEmail,
isSendingPreviewEmail,
sendingPreviewStatus,
isModalOpened,
} = useSelect((select) => select(storeName).getPreviewState(), []);
const [mailpoetEmailData] = useEntityProp(
'postType',
'mailpoet_email',
'mailpoet_data',
) as [MailPoetEmailData, unknown, unknown];
const handleSendPreviewEmail = () => {
void requestSendingNewsletterPreview(mailpoetEmailData.id, previewToEmail);
};
const closeCallback = () => togglePreviewModal(false);
// We use this effect to focus on the input field when the modal is opened
useEffect(() => {
if (isModalOpened) {
sendToRef.current?.focus();
}
}, [isModalOpened]);
if (!isModalOpened) {
return null;
}
return (
<Modal
className="mailpoet-send-preview-email"
title={__('Send a test email', 'mailpoet')}
onRequestClose={closeCallback}
focusOnMount={false}
>
{sendingPreviewStatus === SendingPreviewStatus.ERROR ? (
<div className="mailpoet-send-preview-modal-notice-error">
{__('Sorry, we were unable to send this email.', 'mailpoet')}
<ul>
<li>
{createInterpolateElement(
__(
'Please check your <link>sending method configuration</link> with your hosting provider.',
'mailpoet',
),
{
link: (
// eslint-disable-next-line jsx-a11y/anchor-has-content, jsx-a11y/control-has-associated-label
<a
href="admin.php?page=mailpoet-settings#mta"
target="_blank"
rel="noopener noreferrer"
/>
),
},
)}
</li>
<li>
{createInterpolateElement(
__(
'Or, sign up for MailPoet Sending Service to easily send emails. <link>Sign up for free</link>',
'mailpoet',
),
{
link: (
// eslint-disable-next-line jsx-a11y/anchor-has-content, jsx-a11y/control-has-associated-label
<a
href={new URL(
'free-plan',
'https://www.mailpoet.com/',
).toString()}
key="sign-up-for-free"
target="_blank"
rel="noopener noreferrer"
/>
),
},
)}
</li>
</ul>
</div>
) : null}
<p>
{createInterpolateElement(
__(
'Send yourself a test email to test how your email would look like in different email apps. You can also test your spam score by sending a test email to <link1>{$serviceName}</link1>. <link2>Learn more</link2>.',
'mailpoet',
).replace('{$serviceName}', 'Mail Tester'),
{
link1: (
// eslint-disable-next-line jsx-a11y/anchor-has-content, jsx-a11y/control-has-associated-label
<a
href="https://www.mail-tester.com/"
target="_blank"
rel="noopener noreferrer"
/>
),
link2: (
// eslint-disable-next-line jsx-a11y/anchor-has-content, jsx-a11y/control-has-associated-label
<a
href="https://kb.mailpoet.com/article/147-test-your-spam-score-with-mail-tester"
target="_blank"
rel="noopener noreferrer"
/>
),
},
)}
</p>
<TextControl
label={__('Send to', 'mailpoet')}
onChange={(email) => {
void updateSendPreviewEmail(email);
}}
onKeyDown={(event) => {
const { keyCode } = event;
if (keyCode === ENTER) {
event.preventDefault();
handleSendPreviewEmail();
}
}}
value={previewToEmail}
type="email"
ref={sendToRef}
required
/>
{sendingPreviewStatus === SendingPreviewStatus.SUCCESS ? (
<p className="mailpoet-send-preview-modal-notice-success">
<Icon icon={check} style={{ fill: '#4AB866' }} />
{__('Test email sent successfully!', 'mailpoet')}
</p>
) : null}
<div className="mailpoet-send-preview-modal-footer">
<Button variant="tertiary" onClick={closeCallback}>
{__('Close', 'mailpoet')}
</Button>
<Button
variant="primary"
onClick={handleSendPreviewEmail}
disabled={isSendingPreviewEmail || !isEmail(previewToEmail)}
>
{isSendingPreviewEmail
? __('Sending...', 'mailpoet')
: __('Send test email', 'mailpoet')}
</Button>
</div>
</Modal>
);
}

View File

@ -1,63 +0,0 @@
import { hasBlockSupport, getBlockSupport } from '@wordpress/blocks';
import { Fill, Notice } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
export const hasBackgroundImageSupport = (nameOrType: string) => {
// @ts-expect-error not yet supported in the types
const backgroundSupport = getBlockSupport(nameOrType, 'background') as Record<
string,
boolean
>;
return backgroundSupport && backgroundSupport?.backgroundImage !== false;
};
export function BlockCompatibilityWarnings(): JSX.Element {
// Select the currently selected block
const selectedBlock = useSelect(
(sel) => sel('core/block-editor').getSelectedBlock(),
[],
);
// Check if the selected block has enabled border configuration
const hasBorderSupport = hasBlockSupport(
selectedBlock?.name,
// @ts-expect-error Border is not yet supported in the types
'__experimentalBorder',
false,
);
return (
<>
{hasBorderSupport && (
<Fill name="InspectorControlsBorder">
<Notice
className="mailpoet__grid-full-width"
status="warning"
isDismissible={false}
>
{__(
'Border display may vary or be unsupported in some email clients.',
'mailpoet',
)}
</Notice>
</Fill>
)}
{hasBackgroundImageSupport(selectedBlock?.name) && (
<Fill name="InspectorControlsBackground">
<Notice
className="mailpoet__grid-full-width"
status="warning"
isDismissible={false}
>
{__(
'Select a background color for email clients that do not support background images.',
'mailpoet',
)}
</Notice>
</Fill>
)}
</>
);
}

View File

@ -1,131 +0,0 @@
import {
__experimentalText as Text,
ExternalLink,
PanelBody,
TextareaControl,
} from '@wordpress/components';
import { useDispatch } from '@wordpress/data';
import { useEntityProp } from '@wordpress/core-data';
import { __ } from '@wordpress/i18n';
import { createInterpolateElement } from '@wordpress/element';
import classnames from 'classnames';
import { storeName } from '../../store';
const previewTextMaxLength = 150;
const previewTextRecommendedLength = 80;
export function DetailsPanel() {
const [mailpoetEmailData] = useEntityProp(
'postType',
'mailpoet_email',
'mailpoet_data',
);
const { updateEmailMailPoetProperty } = useDispatch(storeName);
const subjectHelp = createInterpolateElement(
__(
'Use shortcodes to personalize your email, or learn more about <bestPracticeLink>best practices</bestPracticeLink> and using <emojiLink>emoji in subject lines</emojiLink>.',
'mailpoet',
),
{
bestPracticeLink: (
// eslint-disable-next-line jsx-a11y/anchor-has-content, jsx-a11y/control-has-associated-label
<a
href="https://www.mailpoet.com/blog/17-email-subject-line-best-practices-to-boost-engagement/"
target="_blank"
rel="noopener noreferrer"
/>
),
emojiLink: (
// eslint-disable-next-line jsx-a11y/anchor-has-content, jsx-a11y/control-has-associated-label
<a
href="https://www.mailpoet.com/blog/tips-using-emojis-in-subject-lines/"
target="_blank"
rel="noopener noreferrer"
/>
),
},
);
const subjectLabel = (
<>
<span>{__('Subject', 'mailpoet')}</span>
<ExternalLink href="https://kb.mailpoet.com/article/215-personalize-newsletter-with-shortcodes#list">
{__('Shortcode guide', 'mailpoet')}
</ExternalLink>
</>
);
const previewTextLength = mailpoetEmailData?.preheader?.length ?? 0;
const preheaderLabel = (
<>
<span>{__('Preview text', 'mailpoet')}</span>
<span
className={classnames('mailpoet-settings-panel__preview-text-length', {
'mailpoet-settings-panel__preview-text-length-warning':
previewTextLength > previewTextRecommendedLength,
'mailpoet-settings-panel__preview-text-length-error':
previewTextLength > previewTextMaxLength,
})}
>
{previewTextLength}/{previewTextMaxLength}
</span>
</>
);
return (
<PanelBody
title={__('Details', 'mailpoet')}
className="mailpoet-email-editor__settings-panel"
>
<TextareaControl
className="mailpoet-settings-panel__subject"
label={subjectLabel}
placeholder={__('Eg. The summer sale is here!', 'mailpoet')}
value={mailpoetEmailData?.subject ?? ''}
onChange={(value) => updateEmailMailPoetProperty('subject', value)}
data-automation-id="email_subject"
/>
<div className="mailpoet-settings-panel__help">
<Text>{subjectHelp}</Text>
</div>
<TextareaControl
className="mailpoet-settings-panel__preview-text"
label={preheaderLabel}
placeholder={__(
"Add a preview text to capture subscribers' attention and increase open rates.",
'mailpoet',
)}
value={mailpoetEmailData?.preheader ?? ''}
onChange={(value) => updateEmailMailPoetProperty('preheader', value)}
data-automation-id="email_preview_text"
/>
<div className="mailpoet-settings-panel__help">
<Text>
{createInterpolateElement(
__(
'<link>This text</link> will appear in the inbox, underneath the subject line.',
'mailpoet',
),
{
link: (
// eslint-disable-next-line jsx-a11y/anchor-has-content, jsx-a11y/control-has-associated-label
<a
href={new URL(
'article/418-preview-text',
'https://kb.mailpoet.com/',
).toString()}
key="preview-text-kb"
target="_blank"
rel="noopener noreferrer"
/>
),
},
)}
</Text>
</div>
</PanelBody>
);
}

Some files were not shown because too many files have changed in this diff Show More