Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
400 changes: 348 additions & 52 deletions assets/css/builder.css

Large diffs are not rendered by default.

Binary file added assets/img/mailpoet-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/mailpoet-symbol.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
99 changes: 85 additions & 14 deletions assets/js/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -1739,9 +1739,9 @@ var allTerrainFormsBuilder = function(exports) {
const parsed = parseFloat(String(value ?? ""));
return Number.isFinite(parsed) ? parsed : fallback2;
}
function nearest(value, steps) {
let best = steps[0];
for (const step of steps) {
function nearest(value, steps2) {
let best = steps2[0];
for (const step of steps2) {
if (Math.abs(step.at - value) < Math.abs(best.at - value)) {
best = step;
}
Expand Down Expand Up @@ -2570,13 +2570,18 @@ var allTerrainFormsBuilder = function(exports) {
}
function formCard(summary, info, host) {
const card = el("section", { class: "atfm-form" });
const mark = (on) => el("span", {
class: `atfm-form__mark${on ? "" : " atfm-form__mark--off"}`,
children: [el("img", { attrs: { src: info.symbol, alt: "", width: "20", height: "20" } })]
});
const paintClosed = (subscribed) => {
clear(card);
card.classList.remove("is-open");
card.append(
el("div", {
class: "atfm-form__head",
children: [
mark(subscribed.length > 0),
el("div", {
class: "atfm-form__title",
children: [
Expand Down Expand Up @@ -2690,10 +2695,12 @@ var allTerrainFormsBuilder = function(exports) {
paintClosed(remove ? [] : info.lists.filter((list) => chosen.has(list.id)).map((list) => list.name));
};
clear(card);
const caption = (text) => el("span", { class: "atfm-form__section", text });
card.append(
el("div", {
class: "atfm-form__head",
children: [
mark(Boolean(action)),
el("div", {
class: "atfm-form__title",
children: [el("strong", { text: summary.title || `Form ${summary.id}` })]
Expand All @@ -2704,7 +2711,9 @@ var allTerrainFormsBuilder = function(exports) {
el("div", {
class: "atfm-form__body",
children: [
row("Lists", listsBox, "Where the subscriber lands. MailPoet sends its own confirmation email first."),
caption("Where they land"),
row("Lists", listsBox, "MailPoet sends its own confirmation email before anyone is truly on a list."),
caption("Who they are"),
row(
"Email address",
select(email, fieldOptions(fields, "— pick a field —"), (value) => {
Expand All @@ -2724,6 +2733,7 @@ var allTerrainFormsBuilder = function(exports) {
lastName = value;
})
),
caption("When to subscribe"),
row(
"Subscribe",
select(
Expand Down Expand Up @@ -2765,7 +2775,7 @@ var allTerrainFormsBuilder = function(exports) {
class: "atfm-hero__logo",
children: [
el("img", {
attrs: { src: info.logo, alt: "MailPoet", width: "108", height: "65" }
attrs: { src: info.logo, alt: "MailPoet", width: "210", height: "105" }
})
]
}) : el("span", { class: "atfm-hero__logo atfm-hero__logo--glyph", text: "📬" });
Expand All @@ -2776,22 +2786,77 @@ var allTerrainFormsBuilder = function(exports) {
el("div", {
class: "atfm-hero__words",
children: [
el("h1", { text: "Grow your audience where it begins" }),
el("h1", { text: "Turn submissions into subscribers" }),
el("p", {
text: "Every submission is someone choosing to talk to you. Connect a form to MailPoet and the ones who opt in land on your lists by themselves — named, consented, and confirmed by MailPoet’s own double opt-in."
}),
info.active ? el("p", {
class: "atfm-hero__status is-on",
text: 1 === info.lists.length ? "Connected — 1 list available" : `Connected — ${info.lists.length} lists available`
text: 1 === info.lists.length ? "Connected — 1 list ready for subscribers" : `Connected — ${info.lists.length} lists ready for subscribers`
}) : el("p", {
class: "atfm-hero__status",
text: "MailPoet is not installed on this site yet."
text: "MailPoet is not installed on this site yet"
})
]
})
]
});
}
function whyMailPoet() {
const card = (icon2, title, words) => el("div", {
class: "atfm-why__card",
children: [
el("span", { class: "atfm-why__icon", text: icon2 }),
el("strong", { text: title }),
el("p", { text: words })
]
});
const link = (href, text) => el("a", { text, attrs: { href, target: "_blank", rel: "noreferrer" } });
return [
el("div", {
class: "atfm-why",
children: [
card(
"✉️",
"Beautiful emails, made in WordPress",
"Design newsletters and welcome emails in a drag-and-drop editor that lives in your own admin — no external account to juggle."
),
card(
"🤝",
"Consent you can stand behind",
"Double opt-in out of the box: every address your forms send over is confirmed by the visitor before a single campaign reaches it."
),
card(
"🚀",
"Free to grow with",
"Free up to 500 subscribers, welcome automations, WooCommerce emails and open-rate stats included — a paid addon anywhere else."
)
]
}),
el("p", {
class: "atfm-links",
children: [
link("https://www.mailpoet.com/features/", "Explore MailPoet’s features ↗"),
link("https://kb.mailpoet.com/", "Guides & docs ↗"),
link("https://www.mailpoet.com/pricing/", "Plans & the free tier ↗")
]
})
];
}
function steps() {
const step = (n, words) => el("div", {
class: "atfm-step",
children: [el("span", { class: "atfm-step__n", text: n }), el("span", { text: words })]
});
return el("div", {
class: "atfm-steps",
children: [
step("1", "Pick a form below"),
step("2", "Choose the lists it feeds"),
step("3", "Bind it to an opt-in — MailPoet confirms the rest")
]
});
}
async function mountMailPoetHub() {
const root = document.querySelector("[data-atfm-root]");
if (!root || root.dataset.atfmMounted) {
Expand All @@ -2805,7 +2870,7 @@ var allTerrainFormsBuilder = function(exports) {
const [info, forms] = await Promise.all([api.mailpoet(), api.listForms()]);
bar?.remove();
clear(body);
body.append(hero(info));
body.append(hero(info), ...whyMailPoet());
if (!info.active) {
body.append(
el("div", {
Expand All @@ -2816,7 +2881,7 @@ var allTerrainFormsBuilder = function(exports) {
}),
el("a", {
class: "atfm-pitch__cta",
text: "Install MailPoet",
text: "Install MailPoet — it’s free",
attrs: { href: info.adminUrl, target: "_blank", rel: "noreferrer" }
})
]
Expand All @@ -2842,13 +2907,19 @@ var allTerrainFormsBuilder = function(exports) {
);
return;
}
body.append(steps());
const section = el("section", {
class: "atfm-forms",
children: [
el("h2", { text: "Your forms" }),
el("p", {
class: "atfm-hint",
text: "Pick a form, choose its lists, and bind the subscription to an opt-in the visitor actually ticks."
el("div", {
class: "atfm-forms__head",
children: [
el("h2", { text: "Your forms" }),
el("p", {
class: "atfm-hint",
text: "Connected forms wear the MailPoet mark in colour."
})
]
})
]
});
Expand Down
6 changes: 3 additions & 3 deletions assets/js/builder.min.js

Large diffs are not rendered by default.

32 changes: 17 additions & 15 deletions includes/mailpoet.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,28 +103,29 @@ function atf_mailpoet_lists() {
}

/**
* MailPoet's own logo, served from MailPoet's own install.
* MailPoet's wordmark, shipped with this plugin.
*
* Their asset rather than a copy of it: the image only ever renders on a site
* that has MailPoet installed, stays whatever their current release ships, and
* nothing of theirs is redistributed by this plugin.
* Bundled brand assets rather than a file borrowed from MailPoet's install, so
* the window can introduce MailPoet properly *before* it is installed — which
* is exactly when the introduction matters most.
*
* @since 0.2.0
*
* @return string Empty when MailPoet (or the asset) is absent.
* @return string
*/
function atf_mailpoet_logo_url() {
if ( ! atf_mailpoet_active() ) {
return '';
}

$relative = 'mailpoet/assets/img/mailpoet_logo_newsletter.png';

if ( ! file_exists( WP_PLUGIN_DIR . '/' . $relative ) ) {
return '';
}
return ATF_URL . 'assets/img/mailpoet-logo.png';
}

return plugins_url( $relative );
/**
* MailPoet's symbol — the M over the open envelope — for compact badges.
*
* @since 0.2.0
*
* @return string
*/
function atf_mailpoet_symbol_url() {
return ATF_URL . 'assets/img/mailpoet-symbol.png';
}

/**
Expand All @@ -140,6 +141,7 @@ function atf_rest_mailpoet() {
'active' => atf_mailpoet_active(),
'lists' => atf_mailpoet_lists(),
'logo' => atf_mailpoet_logo_url(),
'symbol' => atf_mailpoet_symbol_url(),
// Where "manage your lists" should send people: MailPoet's own
// admin when it is installed, the plugin installer when it is not.
'adminUrl' => atf_mailpoet_active()
Expand Down
8 changes: 5 additions & 3 deletions includes/openstation.php
Original file line number Diff line number Diff line change
Expand Up @@ -364,9 +364,11 @@ function atf_render_analytics_template() {
function atf_render_mailpoet_template() {
?>
<div class="atfm" data-atfm-root>
<div class="atfm__bar" data-atfm-bar>
<os-spinner preset="inline"></os-spinner>
<span class="atfm__loading"><?php esc_html_e( 'Checking MailPoet…', 'allterrain-forms' ); ?></span>
<div class="atfm__boot" data-atfm-bar>
<span class="atfm__boot-mark">
<img src="<?php echo esc_url( atf_mailpoet_symbol_url() ); ?>" alt="" width="34" height="34" />
</span>
<span class="atfm__boot-words"><?php esc_html_e( 'Checking MailPoet…', 'allterrain-forms' ); ?></span>
</div>
<div class="atfm__body" data-atfm-body></div>
</div>
Expand Down
Loading
Loading